2013-05-21 55 views
0

我嘗試使用信號量來同步多個進程。我想,而不是創建每個進程的功能,有可能在一個更通用的方法,用一個單一的功能和一些參數的依賴關係:Python中的進程同步

import multiprocessing 
from multiprocessing import * 

class Worker: 
    def __init__(self, size): 
     self._semaphores = [Semaphore(0)]*(size + 1) 

    def run(self, name, acquire, release): 
     for i in acquire: 
      self._semaphores[i].acquire() 

      print('Running', name) 

     for i in release: 
      self._semaphores[i].release() 

在這種情況下,我有五道工序。第一個從第一個開始,第二個和第三個在第一個之後,第四個在第二個和第三個之後,第五個在第四個之後。

if __name__ == '__main__': 
    worker = Worker(5) 
    Process(target=worker.run, args=('5', [5], [])).start() 
    Process(target=worker.run, args=('4', [4,4], [5])).start() 
    Process(target=worker.run, args=('3', [3], [4])).start() 
    Process(target=worker.run, args=('2', [2], [4])).start() 
    Process(target=worker.run, args=('1', [], [2,3])).start() 

預期輸出是:

Running 1 
Running 2 
Running 3 
Running 4 
Running 5 

但是同步不正常工作。執行是隨機的,包括死鎖。這是爲什麼?

回答

1

[Semaphore(0)]*(size + 1)創建了size + 1引用到Semaphore對象的列表。您需要創建該類的不同實例:

self._semaphores = [Semaphore(0) for _ in range(size + 1)] 
+0

非常感謝,這是絕對正確的!但有一件事我不明白。固定版本不會強制執行預期的訂單。所以輸出仍然是隨機的,但在Windows系統上沒有死鎖。任何想法? – witrin

+0

@witrin:我不完全確定你爲什麼需要信號量。你爲什麼不創建一個進程池並使用'pool.map_sync'來獲得結果? – Blender

+0

因爲它是需要使用信號量的練習的一部分。 – witrin

0

打印的縮進不正確,從而阻止('正在運行','1')。固定之後,打印1張,然後混合2張和3張,接着4張,然後5.2張和3張混合在一起,因爲它們一起被踢出,所以操作如預期。