首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这段代码不会导致竞态条件?

为什么这段代码不会导致竞态条件?
EN

Stack Overflow用户
提问于 2021-03-29 06:24:38
回答 2查看 99关注 0票数 1

我正在解决一个问题,这个问题需要多个线程来更改共享的内存。为了更好地理解python中的工作原理,我开发了以下代码来查看是否可以获得竞态条件:

代码语言:javascript
复制
import threading


class A:
    def __init__(self):
        self.val = 0


def increment(a):
    for _ in range(10):
        a.val += 1


def main():
    a = A()
    threads = [threading.Thread(target=increment, args=(a,)) for _ in range(4)]
    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print(a.val)


if __name__ == '__main__':
    main()

非常简单的东西。每个线程都应该同时尝试递增a.val,这应该会导致竞态条件,因为该值不受锁保护。然而,事实并非如此。每次运行这段代码时,a.val的打印值都是40。因为有四个线程,并且每个线程递增a.val 10倍,所以这是正确的答案。有人能解释为什么这不会导致竞态吗?

EN

回答 2

Stack Overflow用户

发布于 2021-03-29 06:33:39

它确实会导致竞态条件。您当前的范围不足以评估这一点。实际上,在下一个线程可以启动之前,第一个启动的线程已经完成。

具体的数字将花费足够长的时间,不再是这种情况将取决于您的计算机资源,对我来说,将增量函数修改为更大的界限确实会导致val在每次运行时都是不同的值。

代码语言:javascript
复制
def increment(a):
    for _ in range(1_000_000):
        a.val += 1
票数 1
EN

Stack Overflow用户

发布于 2021-03-29 06:31:47

我换成了for _ in range(100000),每次得到的答案都不一样。

否则,我猜在下一个线程旋转之前计算就完成了?实际上,如果我在t.start()之前添加time.sleep(1),结果是“正确的”。

==

这是评论中提出的解决方案(但不是问题的答案):

代码语言:javascript
复制
class A:
    def __init__(self):
        self.val = 0
        self.lock = threading.Lock()

    def __iadd__(self, y):
        with self.lock:
            self.val += y
            return self


def increment(a: A):
    for _ in range(100000):
        a += 1
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66846774

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档