What is Thread Safety as applied to Python?

Removing the GIL does not make functions thread-safe.

Thread-safety relates to this question:

If you have a data structure (say, an object, or a list) that is being modified in one thread, can another thread come along and modify it right in the middle of that calculation?

Let’s say you have a global variable x which equals 0, and two different threads attempt to increment it using this:

x += 1

If incrementing is thread-safe, then you are guaranteed that the result can only be x=2 after the two threads have incremented it. Thread safety guarantees that the only way those two threads can increment x looks like this:

  1. thread A locks x, so nothing else can touch it;
  2. thread A reads the value of x, and gets 0;
  3. thread A adds 1 to the value, giving 1;
  4. thread A writes 1 to x;
  5. thread A unlocks x, so other threads can use it;
  6. thread B locks x;
  7. thread B reads the value of x, and gets 1;
  8. thread B adds 1 to the value, giving 2;
  9. thread B writes 2 to x;
  10. and thread B unlocks x.

Of course the locks and unlocks aren’t free, that takes time, and it also means that thread B has to wait for thread A to finish, which slows it down. So thread-safety isn’t cheap.

But without thread-safety, you can have this:

  1. thread A reads the value of x, and gets 0;
  2. thread B reads the value of x, and gets 0;
  3. thread A adds 1 to the value, giving 1;
  4. thread A writes 1 to x;
  5. thread B adds 1 to the value, giving 1;
  6. thread B writes 1 to x.

So now you have a bug where two threads have both tried to increment x, both think they have done so, but x only equals 1 instead of 2.

Welcome to the Quadrant Of Hell:

2 Likes