【问题标题】:Is sequence unpacking atomic?序列解包是原子的吗?
【发布时间】:2012-11-30 17:02:19
【问题描述】:

序列解包是原子的吗?例如:

(a, b) = (c, d)

我的印象不是。

编辑:我的意思是多线程上下文中的原子性,即整个语句是否像以前的原子一样不可分割。

【问题讨论】:

  • 我的印象是,您可能误解了软件开发中通常理解的原子性。您是在这里谈论线程安全,还是想知道a = c 是否会在b = d 之前执行?
  • @MartijnPieters - 如果 OP 想知道后者,OP 会很困惑为什么像 (a, b) = (b, a) 这样的东西可以用来交换值。一定是线程安全的问题。
  • @TedHopp:这个问题太模糊了,不能这么称呼,根据我的经验,元组拆包本身会引起很多混乱。
  • “原子性”在计算机语言中的意思是“在一个不可分割的步骤中”。如果某些东西是原子的,这意味着操作不能被另一个线程中断。

标签: python variable-assignment atomic


【解决方案1】:

这是一个操作;在应用左侧赋值之前计算右侧表达式:

>>> a, b = 10, 20
>>> a, b
(10, 20)
>>> b, a = a, b
>>> a, b
(20, 10)
>>> a, b = a*b, a/b
>>> a, b
(200, 2)

或者,如果你在谈论多线程环境,那么赋值是不是原子的;解释器使用单个操作码评估元组赋值,但使用单独的操作码将结果存储到每个受影响的变量中:

>>> def t(self): a,b=20,20
... 
>>> dis.dis(t)
  1           0 LOAD_CONST               2 ((20, 20))
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               1 (a)
              9 STORE_FAST               2 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        

然而,正常赋值总是至少有两个操作码(一个用于右手表达式,一个用于存储结果),所以在python中一般 分配不是原子的。序列解包也不例外。

【讨论】:

  • 我认为它不是atomic 表达式。甚至 j = i +1 在高级语言中也不是原子的。我在 python 中有Semaphore....我误解了这个问题?
  • 这并不能确定它是原子的。问题是ab 是否在并发环境中以原子方式(即作为不可分割的操作)分配它们的值。我不相信他们是;也就是说,如果 (a, b) 在最后一步中应该以值 (200, 2) 结束,则另一个线程可能会看到 (200, 10)(20, 2)
  • 我误解了这个问题(或者更确切地说,我选择用关于元组分配的更常见问题来解释这个非常稀疏的问题)。我已对其进行了更新以包含线程安全信息。
  • @GrijeshChauhan:我强烈怀疑 OP 不理解原子性的通常含义。我已经要求澄清。
【解决方案2】:

在多线程环境中绝对不是原子的,使用以下脚本进行测试:

import threading

a, b = 10, 10
finished = False
def thr():
    global finished
    while True:
        # if sequence unpacking and assignment is atomic then (a, b) will always
        # be either (10, 10) or (20, 20).  Could also just check for a != b
        if (a, b) in [(10, 20), (20, 10)]:
            print('Not atomic')
            finished = True
            break

t = threading.Thread(target=thr)
t.start()

while True:
    for i in range(1000000):
        a, b = 20, 20
        a, b = 10, 10
    if finished:
        t.join()
        break

使用 CPython 2.6、2.7 和 3.2 进行测试。在每个版本中,此脚本都会打印“非原子”并在不到一秒的时间内退出。

【讨论】:

  • 你让我重新检查了操作码;解包是一个,但是有两个 STORE_FAST 操作码,每个受影响的变量一个。另一个线程有很多机会在两者之间分配不同的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2011-03-03
  • 2010-12-11
  • 2020-05-07
  • 2013-01-26
  • 2019-07-03
  • 1970-01-01
相关资源
最近更新 更多