Python 并发运行两个线程,两个线程都操作一个变量

Python 并发运行两个线程,两个线程都操作一个变量,python,multithreading,concurrency,race-condition,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):

这是我的密码:

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),但每次运行它,结果都非常不同(小于零)

有什么问题吗?

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

  • 加载
    x的值
  • 计算
    x+1
  • 将计算值存储到
    x
  • 除了线程之外,您可能在步骤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
    

    这可能会带来相当大的开销,因此其他与共享变量接触较少的替代方案可能是更好的选择(以牺牲不同的行为为代价)。

    竞争条件。
    x+=1
    的实际操作大致如下:

  • 加载
    x的值
  • 计算
    x+1
  • 将计算值存储到
    x
  • 除了线程之外,您可能在步骤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
    

    这可能会带来相当大的开销,因此其他与共享变量接触较少的替代方案可能是更好的选择(以牺牲不同的行为为代价)。

    我尝试运行您的代码;我立刻在第三行发现了一个语法错误。也许您尝试发布实际运行的代码?它应该是threading.Thread而不是Thread.threadSee postAlso,
    //在两个线程都完成后
    不是合法的Python注释,而且由于您没有存储对
    a
    b
    实例的引用,当您声称它们真的完成时,我很怀疑;如果你没有在线程上调用
    join
    ,你就不知道它们已经完成了;我立刻在第三行发现了一个语法错误。也许您尝试发布实际运行的代码?它应该是threading.Thread而不是Thread.threadSee postAlso,
    //在两个线程都完成后
    不是合法的Python注释,而且由于您没有存储对
    a
    b
    实例的引用,当您声称它们真的完成时,我很怀疑;如果没有对线程调用
    join
    ,则不知道它们已完成。