并发运行两个线程,它们都操纵单个变量

时间:2016-08-25 11:08:59

标签: python multithreading concurrency race-condition

这是我的代码:

import threading
x=0
class a(threading.thread)
    def run(self):
        global x
        for i in range(1000000):
             x+=1

class b(threading.thread)
    def run(self):
        global x
        for i in range(1000000):
             x-=1
def run():
    a().start()
    b().start()
    //after both thread done
    print x
run()

我希望这显示0(x = 0),但每次运行它时结果都非常不同(小于零)
它有什么问题?

1 个答案:

答案 0 :(得分:5)

比赛条件。 x += 1的实际操作大致是:

  1. 加载x
  2. 的值
  3. 计算x + 1
  4. 将计算值存储到x
  5. 除了线程之外,您可能会在步骤1之后和步骤3之前被其他线程抢占(无论是在2之前还是之后都无关紧要)。如果另一个线程看到未递增的值,减去该值,然后在存储递减的值之前存储递增的值,则只需删除一个增量;如果他们在你做之前存放,你就减少了一笔。

    您需要锁定对共享变量的访问,以确保操作以原子方式运行:

    import threading
    x=0
    xlock = threading.Lock()
    class a(threading.Thread):
        def run(self):
            global x
            for i in range(1000000):
                 with xlock:
                     x+=1
    
    class b(threading.Thread):
        def run(self):
            global x
            for i in range(1000000):
                 with xlock:
                     x-=1
    

    这可能会引入相当多的开销,因此触及共享变量的其他替代方案可能是更好的选择(以牺牲不同的行为为代价)。