0

我有下面的代碼子程序的代碼確保原子

#!/bin/env python 
# http://stackoverflow.com/questions/32192938/order-of-subprocesses-execution-and-its-impact-on-operations-atomicity 

from multiprocessing import Process 
from multiprocessing import Queue 
import time 
import os 

# Define an output queue 
output = Queue() 

# define a example function 
def f(x, output): 

    time.sleep(.5) 
    ppid = os.getppid() # PPID 
    pid = os.getpid()  # PID 
    # very computing intensive operation 
    result = 10*x 
    print "(%s, %s, %s)" % (pp, p, result) 
    time.sleep(.5) 
    # store result as tuple 
    result = (ppid, pid, result) 
    output.put(result) 
    # return result 


def queue_size(queue): 
    size = int(queue.qsize()) 
    print size 

# Print parent pid 
print "Parent pid: %s" % os.getpid() 

# Setup a list of processes that we want to run 
processes = [Process(target=f, args=(x, output)) for x in range(1,11)] 

# Run processes 
for p in processes: 
    p.start() 

# Process has no close attribute 
# for p in processes: 
#  p.close() 

# Exit the completed processes 
for p in processes: 
    p.join() 


# Get process results from the output queue 
print "Order of result might be different from order of print" 
print "See: http://stackoverflow.com/questions/32192938/order-of-subprocesses-execution-and-its-impact-on-operations-atomicity" 
print "" 
results = [output.get() for p in processes] 
print(results) 

,我想用多個語句這樣的替換print "(%s, %s, %s)" % (pp, p, result)

print "ppid: %s" % ppid 
print "pid: %s" % pid 
print "result: %s" % result 
print "#####################" 

爲此,我選擇信號燈,以確保此輸出將是原子的。這是修改後的版本:

#!/bin/env python 
# http://stackoverflow.com/questions/32192938/order-of-subprocesses-execution-and-its-impact-on-operations-atomicity 

from multiprocessing import Process 
from multiprocessing import Queue 
import threading 
import time 
import os 

max_threads = 1 
semaphore = threading.BoundedSemaphore(max_threads) 

# Define an output queue 
output = Queue() 

# define a example function 
def f(x, output): 

    time.sleep(.5) 
    ppid = os.getppid() # PPID 
    pid = os.getpid()  # PID 
    # very computing intensive operation 
    result = 10*x 

    # print "(%s, %s, %s)" % (pp, p, result) 
    semaphore.acquire() 
    print "ppid: %s" % ppid 
    print "pid: %s" % pid 
    print "result: %s" % result 
    print "#####################" 
    semaphore.release() 

    time.sleep(.5) 
    # store result as tuple 
    result = (ppid, pid, result) 
    output.put(result) 
    # return result 


def queue_size(queue): 
    size = int(queue.qsize()) 
    print size 

# Print parent pid 
print "Parent pid: %s" % os.getpid() 

# Setup a list of processes that we want to run 
processes = [Process(target=f, args=(x, output)) for x in range(1,11)] 

# Run processes 
for p in processes: 
    p.start() 

# Process has no close attribute 
# for p in processes: 
#  p.close() 

# Exit the completed processes 
for p in processes: 
    p.join() 


# Get process results from the output queue 
print "Order of result might be different from order of print" 
print "See: http://stackoverflow.com/questions/32192938/order-of-subprocesses-execution-and-its-impact-on-operations-atomicity" 
print "" 
results = [output.get() for p in processes] 
print(results) 

但似乎這些操作不是原子(PID 10269和10270 PID),和信號燈沒有幫助,這裏是輸出:

Parent pid: 10260 
ppid: 10260 
pid: 10264 
result: 40 
##################### 
ppid: 10260 
pid: 10263 
result: 30 
##################### 
ppid: 10260 
pid: 10265 
result: 50 
##################### 
ppid: 10260 
pid: 10262 
result: 20 
##################### 
ppid: 10260 
pid: 10267 
result: 70 
##################### 
ppid: 10260 
pid: 10268 
result: 80 
##################### 
ppid: 10260 
pid: 10261 
result: 10 
##################### 
ppid: 10260 
ppid: 10260 
pid: 10269 
pid: 10270 
result: 90 
result: 100 
##################### 
##################### 
ppid: 10260 
pid: 10266 
result: 60 
##################### 
Order of result might be different from order of print 
See: http://stackoverflow.com/questions/32192938/order-of-subprocesses-execution-and-its-impact-on-operations-atomicity 

[(10260, 10264, 40), (10260, 10263, 30), (10260, 10265, 50), (10260, 10267, 70), (10260, 10262, 20), (10260, 10268, 80), (10260, 10261, 10), (10260, 10270, 100), (10260, 10269, 90), (10260, 10266, 60)] 

爲什麼?

回答

2

您正在使用進程運行f,但您嘗試使用線程信號進行同步。您在這裏混合了不兼容的多任務模型。在程序中使用的進程在不同的內存空間中運行,並具有獨立的程序計數器,這意味着無法像在單個程序中一樣運行它們。線程在單個程序,共享內存中運行它們。

我的意思是,processes中的每個進程都將作爲一個獨立程序運行。您可以嘗試使用multiprocessing.Lock,但我認爲鎖定獨立程序僅打印調試輸出是沒有意義的。

相反,我建議你改變你的打印語句:

print("ppid: {}\n" 
     "pid: {}\n" 
     "result: \n" 
     "#####################".format(ppid, pid, result)) 

注意,你可以把分隔字符串和Python解釋器可以自動加入他們的行列。還引入\n插入換行符。我也改爲print()函數和格式(),不推薦使用%

使用此方法,混合輸出的可能性較小,但仍可能發生。如果不夠好,請使用multiprocessing.Lock而不是threading.Lock,不需要進一步修改代碼。

+0

謝謝你的回覆。 「我認爲鎖定獨立程序僅打印調試輸出是沒有意義的。」我同意,這僅僅是一個例子,作爲初學者,我想知道所選擇的方法對於更復雜的關鍵部分是否正確。使用鎖(或者可能是信號量)可能是最好的方法。有一件事是用戶應該知道的是使用鎖作爲全局變量,這裏的更多信息http://stackoverflow.com/questions/28267972/python-multiprocessing-locks –