web-dev-qa-db-ja.com

Pythonでのmutexの適切な使用

私はpython(または少なくとも私のスクリプトが複数のスレッドを作成する可能性があります)のマルチスレッドから始めています。このアルゴリズムはミューテックスの正しい使い方でしょうか?これをテストしていません。まだコードがあり、おそらく動作しません。キューにスレッドが存在する場合でも、processDataをスレッド(一度に1つ)で実行し、メインの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

編集:コードを読み直すと、ひどく間違っていることがわかります。でもね、だから私はここで助けを求めています。

64
Richard

Pythonの代わりにWindowのMutexを使用している理由がわかりません。 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 )により、いずれにしても1つのスレッドのみが事実上一度に実行されることに注意してください。ただし、I/Oバウンドスレッドが他のスレッドの実行をブロックしないように、可能な限りロックを解除する必要があります。

Python 2.6以降では、Pythonのmultiprocessingパッケージを使用します。これはthreadingパッケージをミラーリングしますが、can同時に実行します。例を更新するのは簡単です。

from multiprocessing import Process, Lock

mutex = Lock()

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

if __== '__main__':
    while True:
        p = Process(target = processData, args = (some_data,))
        p.start()
138
Chris B.

これは私が思いついた解決策です:

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
13
Richard

いつかミューテックスのロックを解除する必要があります...

answer from 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

Whileループでthread_safe = Falseを設定した場合の最初の実行では、mutexは使用されず、スレッドは以下のようにprintメソッドで互いにステップオーバーします。

Not Thread safe

ただし、thread_safe = Trueを設定して実行すると、すべての出力が完全に正常に表示されます。

Thread safe

お役に立てれば。

5
Teoman shipahi