Anton Bryzgalov <[email protected]> added the comment:
Example code (also is attached to the issue):
import asyncio
async def count_smth(seconds: int) -> int:
await asyncio.sleep(seconds)
return seconds * 3
async def small_job(d: dict, key: str, seconds: int) -> None:
d[key] += await count_smth(seconds) # <-- strange happens here
async def main() -> None:
d = dict(key=0)
await asyncio.gather(
small_job(d, 'key', 1),
small_job(d, 'key', 2),
)
print(d['key']) # expected: 0 + 1 * 3 + 2 * 3 = 9, actual: 6
if __name__ == '__main__':
asyncio.run(main())
Expected output: 0 + 1 * 3 + 2 * 3 = 9. Actual: 6. Seems to be a race condition.
Same happens for other immutable types: str, tuple (when used as values of dict
instead of int). But works correctly with list and custom class with __iadd__
method.
Same effect for treading version (output is the same):
import time
import threading
def count_smth(seconds: int) -> int:
time.sleep(seconds)
return seconds * 3
def small_job(d: dict, key: str, seconds: int) -> None:
d[key] += count_smth(seconds) # <-- strange happens here
def main() -> None:
d = dict(key=0)
t1 = threading.Thread(target=small_job, args=(d, 'key', 1))
t2 = threading.Thread(target=small_job, args=(d, 'key', 2))
t1.start()
t2.start()
t1.join()
t2.join()
print(d['key']) # expected: 0 + 1 * 3 + 2 * 3 = 9, actual: 6
main()
Inplace operation is expected to occur only at the time when the second operand
is evaluated.
----------
Added file: https://bugs.python.org/file48718/inplace_bug_threading.py
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue38817>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com