0

Obviously, lists themselves are not thread safe. However, some operations on them are atomic meaning that no thread can force itself into the execution of that instruction.

Assuming that L is a list:

L = [1,2,3,4]

I know that

x = L[2] # is atomic. 

Now assuming that I have a list of list;

L = [ [1, 2, 3], [4, 5, 6] ]

Further, assume the entire list structure is fixed but the individual values are not i.e. there will always be 2 lists of 3 items.

I know that L[1] = [7,8,9] is atomic meaning L[1] will at some point change to exactly [7,8,9] however there is no guarantee when or for how long.

  1. Is L[1][2] = 10 atomic?
  2. x = L[1] is still atomic right?
  3. Do the answers to 1. and 2. hold irrespective of what the list items are i.e. list of objects?

I think all the answers are yes, but don't know.

Paul O
  • 425
  • 5
  • 19
  • of course, `L[1][2] = 10` could not be safe in case if `L[1]` is dynamic/mutable value **shared** between many threads – RomanPerekhrest Nov 08 '17 at 13:43
  • 1
    https://stackoverflow.com/questions/6319207/are-lists-thread-safe – Theo Nov 08 '17 at 13:46
  • @RomanPerekhrest TY for your answer but what I mean by thread safe is L[1][2] will at some point change to exactly [10] however there is no guarantee when or for how long. – Paul O Nov 08 '17 at 14:06
  • @Theo I had read all of the answers to that link and their subsequent links but was not sure if it also applied to lists of lists and whether it was indifferent to the item types in the list – Paul O Nov 08 '17 at 14:10
  • 1
    `list`s aren't thread-safe, regardless of their contents. `list`s-of-`list`s doubly so. – martineau Nov 08 '17 at 14:35

1 Answers1

0

No. Generally no.

We know that a single bytecode instruction is atomic in CPython, but a = does not have to result in a single bytecode instruction:

>>> import diss
>>> l = [1,2]
>>> def foo():
...    global l
...    x = l[1]
... 
>>> dis.dis(foo)
  3           0 LOAD_GLOBAL              0 (l)
              3 LOAD_CONST               1 (1)
              6 BINARY_SUBSCR       
              7 STORE_FAST               0 (x)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        
>>> 

This = op is interpreted into 3 bytecode instructions (from index 3 to 7), that means one thread could give up GIL and let other thread in which makes modifications then return GIL to the first thread. This is where surprises happen.

So whenever you need thread safety, use a lock.

Axl Wang
  • 21
  • 4
  • Are you sure as that is contrary to [link](HTTP://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm) – Paul O Nov 08 '17 at 17:25
  • @PaulO Yes, I'm pretty sure. Here lists (and other critical built-in types) are thread safe means that concurrent access won't corrupt list itself but no guarantees are made for list's data. check this out http://effbot.org/zone/thread-synchronization.htm – Axl Wang Nov 08 '17 at 18:22
  • 1
    But what about [https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe](https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe) it says L1[i:j] = L2 is atomic (Thank you for answering I jsut want to make sure the answer is right) – Paul O Nov 09 '17 at 16:55