Python中互斥锁的正确使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3310049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:23:45  来源:igfitidea点击:

Proper use of mutexes in Python

pythonmultithreadingmutex

提问by Richard

I am starting with multi-threads in python (or at least it is possible that my script creates multiple threads). would this algorithm be the right usage of a Mutex? I haven't tested this code yet and it probably won't even work. I just want processData to run in a thread (one at time) and the main while loop to keep running, even if there is a thread in queue.

我从 python 中的多线程开始(或者至少我的脚本有可能创建多个线程)。这个算法是互斥锁的正确用法吗?我还没有测试过这段代码,它甚至可能不起作用。我只希望 processData 在一个线程中运行(一次一个)并且主 while 循环继续运行,即使队列中有一个线程。

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

Edit: re-reading my code I can see that it is grossly wrong. but hey, that's why I am here asking for help.

编辑:重新阅读我的代码我可以看到它是非常错误的。但是,嘿,这就是我来这里寻求帮助的原因。

采纳答案by Chris B.

I don't know why you're using the Window's Mutex instead of Python's. Using the Python methods, this is pretty simple:

我不知道你为什么使用 Window 的 Mutex 而不是 Python 的。使用 Python 方法,这非常简单:

from threading import Thread, Lock

mutex = Lock()

def processData(data):
    mutex.acquire()
    try:
        print('Do some stuff')
    finally:
        mutex.release()

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

But note, because of the architecture of CPython (namely the Global Interpreter Lock) you'll effectively only have one thread running at a time anyway--this is fine if a number of them are I/O bound, although you'll want to release the lock as much as possible so the I/O bound thread doesn't block other threads from running.

但请注意,由于 CPython 的架构(即Global Interpreter Lock),无论如何您一次只能有效地运行一个线程——如果其中许多线程受 I/O 限制,这很好,尽管您会想要尽可能多地释放锁,以便 I/O 绑定线程不会阻止其他线程运行。

An alternative, for Python 2.6 and later, is to use Python's multiprocessingpackage. It mirrors the threadingpackage, but will create entirely new processes which canrun simultaneously. It's trivial to update your example:

对于 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()

回答by Guillaume Lebourgeois

You have to unlock your Mutex at sometime...

你必须在某个时候解锁你的互斥锁...

回答by Richard

This is the solution I came up with:

这是我想出的解决方案:

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

Output:

输出:

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

回答by Teoman shipahi

I would like to improve answerfrom chris-ba little bit more.

我想改善的答案克里斯-B多一点点。

See below for my code:

请参阅下面的我的代码:

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

In your first run if you set thread_safe = Falsein while loop, mutex will not be used, and threads will step over each others in print method as below;

在你第一次运行时,如果你thread_safe = False在 while 循环中设置,则不会使用互斥锁,线程将在打印方法中相互跳过,如下所示;

Not Thread safe

不是线程安全的

but, if you set thread_safe = Trueand run it, you will see all the output comes perfectly fine;

但是,如果你设置thread_safe = True并运行它,你会看到所有的输出都完美无缺;

Thread safe

线程安全

hope this helps.

希望这可以帮助。