Правильное использование мьютексов в Python
Я начинаю с многопотоков в python (или, по крайней мере, возможно, что мой script создает несколько потоков). будет ли этот алгоритм правильным использованием Mutex? Я еще не тестировал этот код, и он, вероятно, даже не будет работать. Я просто хочу, чтобы 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
Изменить: перечитывать мой код. Я вижу, что это очень неправильно. но эй, вот почему я здесь прошу о помощи.
Ответы
Ответ 1
Я не знаю, почему вы используете Mutex Window вместо 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()
Но обратите внимание, что из-за архитектуры CPython (а именно Global Interpreter Lock) у вас фактически будет только один поток, запущенный за раз в любом случае - это хорошо, если число из них связано с вводом-выводом, хотя вы хотите как можно больше освободить блокировку, поэтому связанный поток ввода-вывода не блокирует запуск других потоков.
Альтернативой для 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()
Ответ 2
Это решение, с которым я столкнулся:
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
Ответ 3
Вы должны разблокировать свой Мьютекс когда-нибудь...
Ответ 4
Я хотел бы улучшить ответ из 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
в цикле while, мьютекс не будет использоваться, и потоки будут перешагивать друг друга в методе печати, как показано ниже;
![Not Thread safe]()
но, если вы установите thread_safe = True
и запустите его, вы увидите, что все выходные данные работают отлично;
![Thread safe]()
надеюсь это поможет.