1

In a multi-threading environment, locking should be used before modifying the value of a variable to avoid concurrent write.

Is this true for all types of variables? I am specifically thinking about the case where the values of a dict keys are updated by different threads (possibly at the same time, each thread the value of a different key).

Tim B
  • 40,716
  • 16
  • 83
  • 128
WoJ
  • 27,165
  • 48
  • 180
  • 345

4 Answers4

2

Straight up dict assignment is thread-safe

The GIL yields only in between python bytecode instructions. Operations that take only a single bytecode instruction are safe from the GIL yielding mid operation. dict assignments only take a single operation.

In [4]: import dis

In [5]: x = {}

In [6]: def f():
   ...:     x['test'] = 'test'
   ...:     

In [7]: dis.dis(f)
  2           0 LOAD_CONST               1 ('test')
              3 LOAD_GLOBAL              0 (x)
              6 LOAD_CONST               1 ('test')
              9 STORE_SUBSCR             #<<<<<<<< this OP
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE

If you need to do anything other than a write - in-place add, a read followed by a write, etc - then you're in trouble.

I would argue strongly that this is an implementation detail and actually depending on it to guarantee behavior is asking for trouble. Always provide explicit locks around shared data access.

roippi
  • 25,533
  • 4
  • 48
  • 73
1

In your case you are just changing the value associated with a key, which is an operation on the dictionary. The dict structure itself is thread safe, see here: Thread Safety in Python's dictionary so you should be fine.

If you were making changes inside an object stored in the dictionary then that may have been safe but it may not. If a specific object is only being changed by one thread at a time then that is safe, however if for whatever reason multiple threads start accessing an object at the same time it's not safe.

Community
  • 1
  • 1
Tim B
  • 40,716
  • 16
  • 83
  • 128
  • Thanks, I meant the values (of the keys). I updated my question to clarify. – WoJ Dec 04 '15 at 14:00
  • What do you mean by the values of the keys? – Tim B Dec 04 '15 at 14:01
  • I mean, for `a = {"hello": 3, "world": 4}` to do `a["hello"] = 10`. Does the word "value" in the context of a `dict` always refer to the value assigned to a key? (in which case I will re-clarify my question to use "value") – WoJ Dec 04 '15 at 14:03
  • It's a vague term in general since the value of "hello" is "hello". See my edited answer though, you should be fine – Tim B Dec 04 '15 at 14:07
  • Not safe even if there is only one thread writing or reading to/from the object at the same time. – SergeyA Dec 04 '15 at 14:14
  • @SergeyA Why is your answer different from that in the answer I linked where it says that it is safe? – Tim B Dec 04 '15 at 14:16
  • Dict is thread-safe. But the objects you are writing or reading from, by default, are not. – SergeyA Dec 04 '15 at 14:18
  • Yes but he's not changing any objects, he's just changing the dict - which my first paragraph covers....and changing objects so long as each thread is acting on a different object is safe - which my second paragraph covers...so where's the problem? – Tim B Dec 04 '15 at 14:23
0

I wouldn't worry if it's really multithreading you're dealing with. Threads run within a single process (google GIL) so concurrent write seems improbable.

If you are, by any chance, doing multiprocessing, then sharing data between processes gets much more complicated.

0

Yes, it is inherently unsafe. Even if your updates are done to independent objects within a dictionary, and reads are never happening at the same time with writes, the behaviour of application is undefined.

SergeyA
  • 61,605
  • 5
  • 78
  • 137