面试题答案
一键面试利用Python多变量赋值原子性避免数据竞争问题
在Python中,简单的多变量赋值操作(例如 a, b = b, a
)在CPython解释器下通常是原子性的。这意味着在执行这个操作时,不会被其他线程打断,从而避免了数据竞争问题。
代码实现
import threading
class AtomicSwap:
def __init__(self):
self.a = 0
self.b = 0
def swap(self):
self.a, self.b = self.b, self.a
def worker(atomic_swap):
for _ in range(100000):
atomic_swap.swap()
if __name__ == "__main__":
atomic_swap = AtomicSwap()
threads = []
for _ in range(10):
t = threading.Thread(target=worker, args=(atomic_swap,))
threads.append(t)
t.start()
for t in threads:
t.join()
print(f"Final values: a = {atomic_swap.a}, b = {atomic_swap.b}")
在上述代码中,AtomicSwap
类封装了两个共享变量 a
和 b
,swap
方法通过多变量赋值操作来交换这两个变量的值。多个线程同时调用 swap
方法,由于多变量赋值的原子性,不会出现数据竞争导致结果错误的情况。
局限性
- 依赖解释器:这种原子性是CPython解释器的实现细节,其他Python解释器(如Jython、IronPython等)可能不保证多变量赋值的原子性。因此,代码的可移植性存在问题。
- 操作类型受限:只有简单的多变量赋值操作能保证原子性,对于复杂的操作,如
a = a + b
等,仍然需要使用锁(threading.Lock
)等同步机制来避免数据竞争。 - 复杂场景不适用:当涉及多个共享变量的复杂操作时,仅仅依靠多变量赋值的原子性无法完全解决数据竞争问题,还需要更全面的同步策略。