gpt4 book ai didi

python - `with` 语句 __enter__ 和 __exit__ 线程安全吗?

转载 作者:太空宇宙 更新时间:2023-11-04 03:10:51 25 4
gpt4 key购买 nike

假设:

class A(object):
def __init__(self):
self.cnt = 0
def __enter__(self):
self.cnt += 1
def __exit__(self, exc_type, exc_value, traceback)
self.cnt -= 1
  1. self.cnt += 1在多线程时是否可能被执行两次?
  2. 是否有可能对于同一个上下文管理器实例,在多线程中,__enter__ 被调用两次而 __exit__ 只被调用一次,所以 self. cnt 最终结果是 1?

最佳答案

不能,线程安全只能通过锁来保证。

Is it possible that self.cnt += 1 might be executed twice when multi-threading?

如果你有两个线程运行它,它将被执行两次。三个线程,三次,等等。我不确定你的真正意思,或许可以向我们展示你是如何构建/执行与你的上下文管理器相关的这些线程的。

Is it possible that for the same context manager instance, in multithreading, somehow __enter__ be called twice and __exit__ be called only once, so the self.cnt final result is 1?

是的,最终结果可以是非零的,但不是通过你假设的非对称调用进入和退出的机制。如果您在多个线程中使用相同的上下文管理器实例,您可以构造一个简单的示例来重现如下错误:

from threading import Thread

class Context(object):
def __init__(self):
self.cnt = 0
def __enter__(self):
self.cnt += 1
def __exit__(self, exc_type, exc_value, traceback):
self.cnt -= 1

shared_context = Context()

def run(thread_id):
with shared_context:
print('enter: shared_context.cnt = %d, thread_id = %d' % (
shared_context.cnt, thread_id))
print('exit: shared_context.cnt = %d, thread_id = %d' % (
shared_context.cnt, thread_id))

threads = [Thread(target=run, args=(i,)) for i in range(1000)]

# Start all threads
for t in threads:
t.start()

# Wait for all threads to finish before printing the final cnt
for t in threads:
t.join()

print(shared_context.cnt)

你不可避免地会发现最后的 shared_context.cnt通常不会回到 0 ,即使当所有线程都使用完全相同的代码启动和结束时,即使 enter 和 exit 都或多或少地成对调用:

enter: shared_context.cnt = 3, thread_id = 998
exit: shared_context.cnt = 3, thread_id = 998
enter: shared_context.cnt = 3, thread_id = 999
exit: shared_context.cnt = 3, thread_id = 999
2
...
enter: shared_context.cnt = 0, thread_id = 998
exit: shared_context.cnt = 0, thread_id = 998
enter: shared_context.cnt = 1, thread_id = 999
exit: shared_context.cnt = 0, thread_id = 999
-1

这主要是由 += 引起的运算符被解析为四个操作码,只有 GIL 才能保证单个操作码是安全的。可以在这个问题中找到更多详细信息:Is the += operator thread-safe in Python?

关于python - `with` 语句 __enter__ 和 __exit__ 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38089037/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com