【问题标题】:Python threading. How do I lock a thread?Python 线程。如何锁定线程?
【发布时间】:2012-05-09 22:44:33
【问题描述】:

我正在尝试了解线程和并发的基础知识。我想要一个简单的案例,两个线程反复尝试访问一个共享资源。

代码:

import threading

class Thread(threading.Thread):
    def __init__(self, t, *args):
        threading.Thread.__init__(self, target=t, args=args)
        self.start()
count = 0
lock = threading.Lock()

def increment():
    global count 
    lock.acquire()
    try:
        count += 1    
    finally:
        lock.release()
   
def bye():
    while True:
        increment()
        
def hello_there():
    while True:
        increment()

def main():    
    hello = Thread(hello_there)
    goodbye = Thread(bye)
    
    while True:
        print count

if __name__ == '__main__':
    main()

所以,我有两个线程,都试图增加计数器。我认为如果线程'A'调用increment()lock将被建立,阻止'B'访问直到'A'释放。

运行清楚地表明情况并非如此。您将获得所有随机数据竞赛增量。

锁对象到底是怎么用的?

此外,我尝试将锁放在线程函数中,但仍然没有成功。

【问题讨论】:

  • @Ignacio Vazquez-Abrams - 现在应该。我省略了if __name__ 位。你说的是这个吗?
  • 它也不适合我。我希望您的线程创建看起来像:hello = threading.Thread(target=hello_there),然后启动线程hello.start()
  • 你知道你可以使用with lock:而不是lock.acquire(); try: ...; finally: lock.release()吗?
  • 另外,我不太明白你的问题。代码试图演示什么?
  • 您正确使用了锁。是什么让你认为你不是?

标签: python multithreading


【解决方案1】:

您可以看到,您的锁在您使用它们时几乎可以正常工作,如果您放慢进程并让它们阻塞更多。你有正确的想法,用锁包围关键的代码片段。这是对您的示例的一个小调整,以向您展示每个人如何等待另一个人释放锁定。

import threading
import time
import inspect

class Thread(threading.Thread):
    def __init__(self, t, *args):
        threading.Thread.__init__(self, target=t, args=args)
        self.start()

count = 0
lock = threading.Lock()

def incre():
    global count
    caller = inspect.getouterframes(inspect.currentframe())[1][3]
    print "Inside %s()" % caller
    print "Acquiring lock"
    with lock:
        print "Lock Acquired"
        count += 1  
        time.sleep(2)  

def bye():
    while count < 5:
        incre()

def hello_there():
    while count < 5:
        incre()

def main():    
    hello = Thread(hello_there)
    goodbye = Thread(bye)


if __name__ == '__main__':
    main()

样本输出:

...
Inside hello_there()
Acquiring lock
Lock Acquired
Inside bye()
Acquiring lock
Lock Acquired
...

【讨论】:

  • 哦,太好了!我想我对 main() 中的 print count 显示不稳定的迭代感到困惑。但我想这有点让我同时运行三个循环。谢谢!还有关于检查模块的 TIL。很酷。
  • @Zack:是的,我认为这是让您感到困惑的主要印刷品。它没有任何限制,因此它的打印速度甚至比线程更改它的速度还要快。
  • @jdi 我正在尝试理解锁定,所以我在 count += 1 之后向您的 incre 函数添加了一个 print(count),但是当我运行代码时它会变为 6?
  • @ErinGoBragh 那是因为我们有两个线程试图在计数小于 5 时调用 incre()。一个获得锁,计数变为 5。然后释放锁,另一个线程获得通过,计数变​​为 6。如果将计数保持在 5 或更少非常重要,则需要在获得锁后检查计数,如果为 5,则不执行任何操作
  • 所以用锁等待它可用?
【解决方案2】:
import threading 

# global variable x 
x = 0

def increment(): 
    """ 
    function to increment global variable x 
    """
    global x 
    x += 1

def thread_task(): 
    """ 
    task for thread 
    calls increment function 100000 times. 
    """
    for _ in range(100000): 
        increment() 

def main_task(): 
    global x 
    # setting global variable x as 0 
    x = 0

    # creating threads 
    t1 = threading.Thread(target=thread_task) 
    t2 = threading.Thread(target=thread_task) 

    # start threads 
    t1.start() 
    t2.start() 

    # wait until threads finish their job 
    t1.join() 
    t2.join() 

if __name__ == "__main__": 
    for i in range(10): 
        main_task() 
        print("Iteration {0}: x = {1}".format(i,x))

【讨论】:

  • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 2018-07-28
  • 1970-01-01
  • 2023-03-21
  • 2016-01-21
相关资源
最近更新 更多