Is incr/decr atomic in multithread mode?
Steve Chu
stvchu at gmail.com
Tue Feb 26 02:33:12 UTC 2008
I'm sorry that my expression may confuse you. I try to make it more clear.
My requirement is that clients to incr/decr a value must be atomic,
that get from slabber and
add 1 must be an atomic operation according to clients(php clients or
libmemcached etc.). If two clients incr a value 1, the value should
be 3, not that B client overwrite the value, and the final value is
still 2. This operation in Non-thread is atmoic, because they are not
in concurrent environment, and only one event is processed one time.
But now I found in multithread version it is not atomic, if put the
item_get in add_delta, this may be done, but too many locks.
I wonder if you understand my meaning, anyway,
Cheers,
Steve
On Tue, Feb 26, 2008 at 12:34 AM, dormando <dormando at rydia.net> wrote:
>
> Steve Chu wrote:
> > On Mon, Feb 25, 2008 at 4:28 PM, dormando <dormando at rydia.net> wrote:
> >> Steve Chu wrote:
> >> > On Mon, Feb 25, 2008 at 2:51 PM, dormando <dormando at rydia.net> wrote:
> >> >> I think this is fine?
> >> >>
> >> >> Since the operations are independently atomic, it's perfectly valid for
> >> >> two threads to incr the same value.
> >> >>
> >> >
> >> > But for client api, they seems NOT atomic, because when Thread A just
> >> > has 'item_get' done but before 'add_delta', Thread B can still do
> >> > item_get.
> >> >
> >> > X-> set "foo" 1
> >> > A-> item_get "foo"
> >> > B-> item_get "foo"
> >> > A-> add_delta "foo" by 1
> >> > B-> add_delta "foo" by 1
> >> >
> >> > then A and B both hold value 2, which one should be stored?
> >> >
> >> > And the exact value we need is 3, right? I am not quit sure, correct
> >> > me if i am wrong:)
> >>
> >> The result gets copied into the thread-local 'temp' buffer, then copied
> >> into that connection (implicitly atomic)'s output buffer.
> >>
> >> So actually I read the code wrong the first time. This _should_ do the
> >> right thing:
> >>
> >> We have threads (A, B, X):
> >>
> >> X -> set 'foo' 1
> >>
> >> A -> process_arithmetic_command()
> >> note thread local storage (char temp[])
> >> B -> same.
> >>
> >> A -> it = item_get(key, nkey)
> >> (atomically increments the refcount for that item, returns a reference
> >> to it)
> >> B -> same, same time.
> >> (same)
> >>
> >> A -> out_string(c, add_delta(it, incr, delta, temp));
> >> add_delta runs atomically, copies the result of the addition into the
> >> thread local 'temp' buffer and _returns the 'temp' buffer_ (which
> >> contains 2)
> >> B -> out_string(c, add_delta(it, incr, delta, temp));
> >> Gets serialized behind A, and its 'temp' then holds a value one higher
> >> than A's (containing 3)
> >
> > Here I am confused. Every thread has a local var 'temp' and here
> > 'temp' should hold 2. 'temp' is independent, and doesn't share
> > between threads. So thread B should overwrite the value in the
> > slabber. Am I right?
>
> Yes, it does. Just like it would if the increments happened at
> completely different times. Since the result of the addition is copied
> into the connection's write buffer atomically, this doesn't upset the
> balance of the universe.
>
> Or are you talking about something else?
>
> -Dormando
>
>
--
Steve Chu
http://stvchu.org
More information about the memcached
mailing list