Atomic get and increment in python
For generating continuous unique id's in python I needed a thread safe way to do this:
When disassembling this code we will get this:
which is more pretty anyway.
x = counter counter += 1
2 0 LOAD_FAST 0 (counter)
3 STORE_FAST 1 (x)
3 6 LOAD_FAST 0 (counter)
9 LOAD_CONST 1 (1)
12 INPLACE_ADD
13 STORE_FAST 0 (counter)
As you can see not even counter += 1 is atomic.
Now the obvious solution would be to use a lock. The not so obvious solution is to use a itertools.count().
The counter is implemented in C and doesn't release the GIL so it is atomic. The code would the look like this:
x = counter.next()
Jonas Wagner
Minor comment: itertools.count()
There is no counter() in itertools.
Otherwise this recipe is very helpful, thanks!
Comment by Oleg — 11/25/11 4:40 PM | # - re
Fixed.
Comment by Jonas Wagner — 11/28/11 9:48 AM | # - re
Calling counter.next() is one instruction and storing the result is another. It's possible for another thread to sneak in there. You won't miscount in the way that you would with x+=1, but your idea of the most recent value may be wrong.
For example:
Thread 1: next() # returns 1
Thread 2: next() # returns 2
Thread 2: x = 2
Thread 1: x = 1
Comment by Adam — 3/30/12 10:15 PM | # - re
Sure, but at least for generating id's that seems to be ok for me. Actually it seems to be exactly what's wanted. :)
Comment by Jonas Wagner — 4/3/12 10:04 AM | # - re