5 ms·
I think by “data races” the parent means that code doesn’t lock around operations like += and len(). The data races are there in theory but do not exhibit due t
by shrimpx 3y ago
I think by “data races” the parent means that code doesn’t lock around operations like += and len(). The data races are there in theory but do not exhibit due to the GIL.
- pdonis 3y agoBut this isn't actually true; that was my point. Neither of these operations, if they are part of an actual statement or expression, will complete in a single byte code. That means that, with the GIL, the operations can be interrupted with a thread switch between bytecodes. So, for example, a statement like a += b takes four bytecodes: two LOAD bytecodes to put the values of a and b on the stack, an INPLACE_ADD bytecode to put the result at the top of the stack, and a STORE bytecode to store the result in the variable a. A thread switch could take place in between any two of these bytecodes, and if another thread mutated a or b or was reading the value of a or b, you would have data corruption. The GIL does not prevent this. The only way to prevent it would be to use one of the locking mechanisms provided to guard access to the a and b variables so that only one thread could access them at a time.
- shrimpx 3y agoThank you, I believe you are right. I did try to make a race condition happen using += and am having a hard time. Here's my code import threading i = 0 def test(): global i for x in range(1000000): i += 1 threads = [threading.Thread(target=test) for t in range(20)] for t in threads: t.start() for t in threads: t.join() assert i == 20000000, i Presumably the assert should fail sometimes but I haven't been able to observe that.