参考以下链接:http://docs.python.org/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe
我想知道以下内容:
(x, y) = (y, x)
将在cPython中保证原子。 (x和y都是python变量)
答案 0 :(得分:54)
让我们看看:
>>> x = 1
>>> y = 2
>>> def swap_xy():
... global x, y
... (x, y) = (y, x)
...
>>> dis.dis(swap_xy)
3 0 LOAD_GLOBAL 0 (y)
3 LOAD_GLOBAL 1 (x)
6 ROT_TWO
7 STORE_GLOBAL 1 (x)
10 STORE_GLOBAL 0 (y)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
它们似乎不是原子的:x和y的值可以由LOAD_GLOBAL
字节码之间或之后的ROT_TWO
之间的另一个线程以及{STORE_GLOBAL
之间的另一个线程来更改1}}字节码。
如果要以原子方式交换两个变量,则需要锁定或互斥锁。
对于那些渴望经验证明的人:
>>> def swap_xy_repeatedly():
... while 1:
... swap_xy()
... if x == y:
... # If all swaps are atomic, there will never be a time when x == y.
... # (of course, this depends on "if x == y" being atomic, which it isn't;
... # but if "if x == y" isn't atomic, what hope have we for the more complex
... # "x, y = y, x"?)
... print 'non-atomic swap detected'
... break
...
>>> t1 = threading.Thread(target=swap_xy_repeatedly)
>>> t2 = threading.Thread(target=swap_xy_repeatedly)
>>> t1.start()
>>> t2.start()
>>> non-atomic swap detected
答案 1 :(得分:4)
是的,是的。
Kragen Sitaker 写道:
有人推荐使用这个成语
spam, eggs = eggs, spam
获得线程安全交换。这真的有用吗? (...)
因此,如果此线程在第一个LOAD_FAST之间失去控制权 和最后一个STORE_FAST,一个值可以由另一个线程存储 进入“b”然后会丢失。没有任何保持这一点 从发生,是吗?不。一般来说甚至不简单 赋值必然是线程安全的 因为执行任务可能 在对象上调用特殊方法 他们自己可能需要一个号码 的运作。 希望是对象 将内部锁定它 “国家”价值观,但并非总是如此 案件。
但它确实取决于什么 “线程安全”是指特定的 申请,因为在我心中 这种粒度很多 安全所以很难谈 “线程安全”。关于唯一的事情 Python解释器即将发布 给你免费是内置的 数据类型应该是内部安全的 即使使用本机线程也会出现损坏 换句话说,如果有两个线程
a=0xff
和a=0xff00
,结束了 与一个或另一个,但不是 意外地0xffff
可能是 可能在其他一些语言中如果a 没有受到保护。据说, Python也倾向于 以你可以这样的方式执行 在没有的情况下侥幸逃脱 正式锁定,如果你愿意的话 生活在边缘一点点 暗示对实际的依赖 正在使用的对象。有一个体面的 沿着这些方向进行讨论 c.l.p一会儿 - 搜索 groups.google.com为“关键 部分和互斥体之间的联系 其他
就个人而言,我明确锁定共享 状态(或使用为...设计的结构 正确交换共享信息 在线程中,例如
Queue.Queue
) 在任何多线程应用程序中。至 我认为这是最好的保护 反对维护和进化 这条路。- - David