0

I am teaching a Python course and now reviewing my upcoming material on multi-threading. Last year, I used the following program to demonstrate to students that if two threads try to modify a global variable at the same time, then something messy is going to happen...

#!/usr/bin/env python3
"""Example of a simple race condition"""

import threading

MAX = 1_000_000

# global variable
counter: int = 0


def count() -> None:
    """Target function"""
    global counter
    for _ in range(MAX):
        counter += 1


def main() -> None:
    """Main function"""
    thread1 = threading.Thread(target=count)
    thread2 = threading.Thread(target=count)
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print(f"{counter = :_}")


if __name__ == '__main__':
    main()

But I was astonished to discover that using Python version 3.10, there is no mess at all, and the counter gives the "correct" final value, no matter how many times I run the script, on Windows or Linux.

run example Windows

run example Linux

Python specialists, how can multiple threads update a global variable just fine in Python 3.10 ?

Frederic
  • 1,580
  • 15
  • 15
  • This doesn't demonstrate what you assume. You're printing only the *final* result. Python 3.9 should have produced the same final value if `+=` was an atomic operation. The fact it wasn't would surprise many developers – Panagiotis Kanavos Nov 03 '22 at 11:21
  • IIRC there were lots of internal changes in the Python interpreter between versions 3.9 and 3.10. Perhaps some of them changed the timing for writing to global variables, which will have an effect on this issue. I would consider you just plain lucky that it works without any synchronization. – Some programmer dude Nov 03 '22 at 11:21
  • @Someprogrammerdude this isn't a timing issue. 3.9 should have produced the same result if `+=` was atomic. – Panagiotis Kanavos Nov 03 '22 at 11:23
  • @PanagiotisKanavos Yes, but since `+=` is *not* atomic in Python, differences in bytecode execution time or the use of different bytecode instructions could explain the results. – Some programmer dude Nov 03 '22 at 11:32
  • Don't assume incrementing will remain atomic. In fact, I just remembered that other languages have special interlocked increment methods to ensure increments are atomic. So in `would surprise many developers` I should count myself as well. Even though I never increment global variables this way ... – Panagiotis Kanavos Nov 03 '22 at 11:32
  • @maciek97x Yes, indeed. So I guess I could cancel my own question then... – Frederic Nov 03 '22 at 13:12

0 Answers0