Is incr/decr atomic in multithread mode?

Brian Aker brian at tangent.org
Mon Feb 25 18:18:38 UTC 2008


Hi!

Yep, the single global lock is a problem. I've got working code to fix  
this, but it is a question of what comes first.

1) Remove the non-thread code.
2) Refactor engine.
3) Put locks into new engine code.

It is pretty simple to do a hack job on thread.c right now to do this,  
but I am not sure it makes sense to do this before a couple of other  
pieces are complete.

Hopefully this week I will finish up the number that will tell us what  
it will cost us to only have a threaded version. With that... then we  
can make an informed decision on the first part.

Cheers,
	-Brian

On Feb 25, 2008, at 12:02 PM, Paul van den Bogaard wrote:

> if there are too many mutex calls these can become scalability  
> issues. Solaris 10 has some atomic routines that could be helpfull.
> See http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/atomic.h
>
> for the routines.
>
> Of course if multiple operations are needed that need the protection  
> of a mutex than a atomic operation is no alternative, besides a CPU  
> consuming polling device. And sometimes these come in handy too.
>
> --Paul
>
>
> On 25-feb-2008, at 10:53, 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?
>>
>>> A -> runs out_string(c, temp), with 'temp' having the atomically
>>> incremented value.
>>> A -> inside out_string, copy's the contents of the original 'temp'
>>> buffer into the connection's local write buffer, then sets the
>>> connection into write mode (which will flush its buffer before doing
>>> further processing). Then returns.
>>> A -> returns to the state machine, 'temp' goes to the wolves, etc.
>>> A -> sends value '2' to its client.
>>>
>>> B -> Same thing. Client should receive a '3'.
>>>
>>> Apologies to the original patch author and the list for the  
>>> confusion :)
>>> I had mentally confused "normal" responses and "get" responses,  
>>> which
>>> operate differently.
>>>
>>> -Dormando
>>>
>>>
>>>
>>>>> It's possible that with two threads (A, B):
>>>>>
>>>>> X -> set "foo" 1
>>>>> A -> incr "foo" by 1
>>>>> B -> incr "foo" by 1
>>>>>
>>>>> A -> returns 3
>>>>> B -> returns 3
>>>>>
>>>>> The only guarantee the slabber makes for returning values, is  
>>>>> that they
>>>>> won't get deleted before being transferred through the network.
>>>>>
>>>>> Could be wrong, but that's my impression from checking the  
>>>>> sources.
>>>>>
>>>>> -Dormando
>>>>>
>>>>>
>>>>>
>>>>> Steve Chu wrote:
>>>>>> In 'process_arithmetic_command' function:
>>>>>> We first do item_get from slabs and then do add_delta to incr/ 
>>>>>> decr the value.
>>>>>>
>>>>>> My question is:
>>>>>> Is this atomic in multithread mode? Item_get is atomic and so is
>>>>>> add_delta because they are protected by mutex. But the entire two
>>>>>> operations seems NOT atomic. Two threads can both do item_get  
>>>>>> with
>>>>>> same key, then both incr it, and write back.
>>>>>>
>>>>>> Anybody can tell me whether it is a bug or not?
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> Steve Chu
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>>
>>
>> -- 
>> Steve Chu
>> http://stvchu.org
>
> ---------------------------------------------------------------------------------------------
> Paul van den Bogaard                               Paul.vandenBogaard at sun.com
> ISV-E  -- ISV Engineering, Opensource Engineering group
>
> Sun Microsystems, Inc                              phone:        +31  
> 334 515 918
> Saturnus 1                                                  
> extentsion: x (70)15918
> 3824 ME Amersfoort                                 mobile:       +31  
> 651 913 354
> The Netherlands                                         
> fax:            +31 334 515 001

--
_______________________________________________________
Brian "Krow" Aker, brian at tangent.org
Seattle, Washington
http://krow.net/                     <-- Me
http://tangent.org/                <-- Software
http://exploitseattle.com/    <-- Fun
_______________________________________________________
You can't grep a dead tree.




More information about the memcached mailing list