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