Python中正确使用互斥锁

105 投票
4 回答
228204 浏览
提问于 2025-04-16 01:41

我刚开始学习在Python中使用多线程(或者说我的脚本可能会创建多个线程)。我想知道这个算法是否适合使用互斥锁(Mutex)?我还没有测试这段代码,可能根本就不能运行。我只是想让processData在一个线程中运行(一次只运行一个),而主循环可以继续运行,即使有线程在排队。

from threading import Thread
from win32event import CreateMutex
mutex = CreateMutex(None, False, "My Crazy Mutex")
while(1)
    t = Thread(target=self.processData, args=(some_data,))
    t.start()
    mutex.lock()

def processData(self, data)
    while(1)
        if mutex.test() == False:
            do some stuff
            break

补充:重新看了一下我的代码,我发现它确实有很大的问题。不过,嘿,这就是我来这里寻求帮助的原因。

4 个回答

16

这是我想到的解决办法:

import time
from threading import Thread
from threading import Lock

def myfunc(i, mutex):
    mutex.acquire(1)
    time.sleep(1)
    print "Thread: %d" %i
    mutex.release()


mutex = Lock()
for i in range(0,10):
    t = Thread(target=myfunc, args=(i,mutex))
    t.start()
    print "main loop %d" %i

输出结果:

main loop 0
main loop 1
main loop 2
main loop 3
main loop 4
main loop 5
main loop 6
main loop 7
main loop 8
main loop 9
Thread: 0
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Thread: 5
Thread: 6
Thread: 7
Thread: 8
Thread: 9
21

我想对chris-b的回答做一些改进。

下面是我的代码:

from threading import Thread, Lock
import threading
mutex = Lock()


def processData(data, thread_safe):
    if thread_safe:
        mutex.acquire()
    try:
        thread_id = threading.get_ident()
        print('\nProcessing data:', data, "ThreadId:", thread_id)
    finally:
        if thread_safe:
            mutex.release()


counter = 0
max_run = 100
thread_safe = False
while True:
    some_data = counter        
    t = Thread(target=processData, args=(some_data, thread_safe))
    t.start()
    counter = counter + 1
    if counter >= max_run:
        break

在你第一次运行的时候,如果在循环中把thread_safe = False设置为假,程序就不会使用互斥锁,这样多个线程在打印的时候会互相干扰,结果就会像下面这样;

不安全的线程

但是,如果你把thread_safe = True设置为真再运行,就会看到所有的输出都正常显示了;

安全的线程

希望这对你有帮助。

224

我不太明白你为什么要用Windows的互斥锁,而不是用Python自带的。用Python的方法,其实很简单:

from threading import Thread, Lock

mutex = Lock()

def processData(data):
    with mutex:
        print('Do some stuff')

while True:
    t = Thread(target = processData, args = (some_data,))
    t.start()

不过要注意,由于CPython的架构(也就是全局解释器锁),实际上你一次只能运行一个线程。这样没问题,如果有几个线程是处理输入输出的,但你要尽量释放锁,这样处理输入输出的线程就不会阻碍其他线程运行。

另外一个选择是,从Python 2.6开始,可以使用Python的multiprocessing包。这个包和threading包很像,但它会创建全新的进程,这些进程是可以同时运行的。更新你的例子其实很简单:

from multiprocessing import Process, Lock

mutex = Lock()

def processData(data):
    with mutex:
        print('Do some stuff')

if __name__ == '__main__':
    while True:
        p = Process(target = processData, args = (some_data,))
        p.start()

撰写回答