|
| 1 | +import os |
| 2 | +import pathlib |
| 3 | +import random |
| 4 | +import threading |
| 5 | +import traceback |
| 6 | + |
| 7 | +class GlobalState: |
| 8 | + count = 0 |
| 9 | + |
| 10 | +# Shared variable |
| 11 | +g_value = GlobalState() |
| 12 | +# Lock for synchronization |
| 13 | +lock = threading.Lock() |
| 14 | + |
| 15 | + |
| 16 | +def thread_fn_1(): |
| 17 | + global g_value |
| 18 | + |
| 19 | + iteration = 0 |
| 20 | + while True: |
| 21 | + with lock: |
| 22 | + if iteration % (10 * 1000) == 0: |
| 23 | + print(f"thread 1: {iteration=}") |
| 24 | + old_value = g_value.count |
| 25 | + increment = random.randint(1, 5) |
| 26 | + g_value.count += increment |
| 27 | + assert ( |
| 28 | + g_value.count == old_value + increment |
| 29 | + ), f"{g_value.count=}, {old_value=}, {increment=}" |
| 30 | + iteration += 1 |
| 31 | + |
| 32 | + |
| 33 | +def thread_fn_2(): |
| 34 | + global g_value |
| 35 | + |
| 36 | + iteration = 0 |
| 37 | + while True: |
| 38 | + if iteration % 100 == 0: |
| 39 | + print(f"thread 2: {iteration=}") |
| 40 | + g_value.count += 1 |
| 41 | + iteration += 1 |
| 42 | + |
| 43 | + |
| 44 | +def exception_handler(args): |
| 45 | + traceback.print_exception(args.exc_type, args.exc_value, args.exc_traceback) |
| 46 | + os.abort() |
| 47 | + |
| 48 | + |
| 49 | +def list_current_directory(): |
| 50 | + cwd = pathlib.Path(os.getcwd()) |
| 51 | + for name in cwd.iterdir(): |
| 52 | + print(name) |
| 53 | + |
| 54 | + |
| 55 | +def do_some_prints(): |
| 56 | + x = 3 |
| 57 | + y = 4 |
| 58 | + print(f"Hello from a function call: {x+y=}") |
| 59 | + |
| 60 | + |
| 61 | +def main(): |
| 62 | + print('Issuing a "print" statement') |
| 63 | + do_some_prints() |
| 64 | + |
| 65 | + print("Listing the current directory") |
| 66 | + list_current_directory() |
| 67 | + |
| 68 | + print('Running the "race.cpp" example') |
| 69 | + print() |
| 70 | + # Create two threads |
| 71 | + threading.excepthook = exception_handler |
| 72 | + thread1 = threading.Thread(target=thread_fn_1) |
| 73 | + thread2 = threading.Thread(target=thread_fn_2) |
| 74 | + |
| 75 | + # Start the threads |
| 76 | + thread1.start() |
| 77 | + thread2.start() |
| 78 | + |
| 79 | + # Wait for both threads to finish |
| 80 | + thread1.join() |
| 81 | + thread2.join() |
| 82 | + |
| 83 | + # Print the final value of the shared variable |
| 84 | + print(f"Final {g_value.count=}") |
| 85 | + |
| 86 | + |
| 87 | +if __name__ == "__main__": |
| 88 | + main() |
0 commit comments