python多线程的互斥锁

2020年1月5日 / 30次阅读 / Last Modified 2020年5月13日
多线程

多线程环境下的互斥很常见,python的提供的互斥锁使用起来很简单方便。多线程互斥的难点不是如何使用锁,而是对问题模型的理解和抽象。

下面这段代码,创建几个线程,每个线程都连续打印一个特定字符串,每次打印间隔10毫秒。

$ cat mutex.py
import threading
import time


def p_string(string):
    for i in range(5):
        print(string)
        time.sleep(0.01)

for i in range(3):
    tt = threading.Thread(target=p_string, args=(str(i)*5,))
    tt.start()

由于每次打印都存在10毫秒的延时,可以想象着几个线程的打印是相互交错的。以上代码运行效果如下:

$ python3 mutex.py
00000
11111
22222
00000
11111
22222
11111
00000
22222
00000
11111
22222
00000
11111
22222

现在我们来加一个互斥锁,让每个线程在获取锁后,完成它自己的全部打印,然后在释放锁,让别的线程开始打印。代码如下:

$ cat mutex.py
import threading
import time


mutex = threading.Lock()

def p_string(string):
    mutex.acquire()
    for i in range(5):
        print(string)
        time.sleep(0.01)
    mutex.release()

for i in range(3):
    tt = threading.Thread(target=p_string, args=(str(i)*5,))
    tt.start()

注意增加的3行代码,创建互斥锁,申请锁,释放锁!简单吧。。。修改后的代码,运行效果如下:

$ python3 mutex.py
00000
00000
00000
00000
00000
11111
11111
11111
11111
11111
22222
22222
22222
22222
22222

完美!

需要注意,acquire函数默认是阻塞的,线程执行到这里时,如果无法获取互斥锁,会阻塞等待,直到有线程将锁释放,然后python解释器再调用阻塞在这里的线程。

threading.Lock可以支持非阻塞,即获取不到lock就直接返回False,也可以支持设置阻塞超时时间,下面的acquire函数的官方说明:

acquire(blocking=True, timeout=-1)

    Acquire a lock, blocking or non-blocking.

    When invoked with the blocking argument set to True (the default), block until the lock is unlocked, then set it to locked and return True.

    When invoked with the blocking argument set to False, do not block. If a call with blocking set to True would block, return False immediately; otherwise, set the lock to locked and return True.

    When invoked with the floating-point timeout argument set to a positive value, block for at most the number of seconds specified by timeout and as long as the lock cannot be acquired. A timeout argument of -1 specifies an unbounded wait. It is forbidden to specify a timeout when blocking is false.

    The return value is True if the lock is acquired successfully, False if not (for example if the timeout expired).

    Changed in version 3.2: The timeout parameter is new.

    Changed in version 3.2: Lock acquisition can now be interrupted by signals on POSIX if the underlying threading implementation supports it.

-- EOF --

本文链接:https://www.pynote.net/archives/1732

留言区

《python多线程的互斥锁》有2条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    threading.Lock在acquire的时候,可以设置为非阻塞,也可以设置阻塞的超时时间! [回复]

  • 麦新杰

    函数可重入是一个良好的函数设计,即便还没有多线程的需求。 [回复]


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top