Python Multi-Processing多執行緒程式設計
阿新 • • 發佈:2019-02-16
今天總結一下Python的Multi-Processing多執行緒程式設計。
建立多程序的方法
start new thread
使用thread.start_new_thread是一種最簡單的建立多程序的方法。
#!/usr/bin/python
import thread
import time
# Define a function for the thread
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s"%(threadName, time.ctime(time.time()))
# Create two threads as follows
try:
thread.start_new_thread(print_time, ("Thread-1", 2,))
thread.start_new_thread(print_time, ("Thread-2", 4,))
except:
print "Error: unable to start thread"
while 1:
pass
輸出結果為:
Thread-1: Wed Sep 27 19 :52:57 2017
Thread-2: Wed Sep 27 19:52:59 2017
Thread-1: Wed Sep 27 19:52:59 2017
Thread-1: Wed Sep 27 19:53:01 2017
Thread-1: Wed Sep 27 19:53:03 2017
Thread-2: Wed Sep 27 19:53:03 2017
Thread-1: Wed Sep 27 19:53:05 2017
Thread-2: Wed Sep 27 19:53:07 2017
Thread-2: Wed Sep 27 19:53:11 2017
Thread-2: Wed Sep 27 19 :53:15 2017
如果沒有程式末尾的while無限迴圈,thread1和thread2之外的主執行緒瞬間就會結束,程式就退出了,因此會什麼也不列印。
threading module
#!/usr/bin/python
import threading
import time
exitFlag = 0
class myThread(threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print "Starting " + self.name
print_time(self.name, 5, self.delay)
print "Exiting " + self.name
def print_time(threadName, counter, delay):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
print "Exiting Main Thread"
輸出結果為:
Starting Thread-1
Starting Thread-2
Exiting Main Thread
Thread-1: Wed Sep 27 20:00:16 2017
Thread-2: Wed Sep 27 20:00:17 2017
Thread-1: Wed Sep 27 20:00:17 2017
Thread-1: Wed Sep 27 20:00:18 2017
Thread-2: Wed Sep 27 20:00:19 2017
Thread-1: Wed Sep 27 20:00:19 2017
Thread-1: Wed Sep 27 20:00:20 2017
Exiting Thread-1
Thread-2: Wed Sep 27 20:00:21 2017
Thread-2: Wed Sep 27 20:00:23 2017
Thread-2: Wed Sep 27 20:00:25 2017
Exiting Thread-2
也可以通過加入執行緒列表的形式,等待執行緒執行結束後主執行緒才退出:
#!/usr/bin/python
import threading
import time
exitFlag = 0
class myThread(threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print "Starting " + self.name
print_time(self.name, 5, self.delay)
print "Exiting " + self.name
def print_time(threadName, counter, delay):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads = []
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print "Exiting Main Thread"
輸出結果為:
Starting Thread-1
Starting Thread-2
Thread-1: Wed Sep 27 20:04:21 2017
Thread-1: Wed Sep 27 20:04:22 2017
Thread-2: Wed Sep 27 20:04:22 2017
Thread-1: Wed Sep 27 20:04:23 2017
Thread-2: Wed Sep 27 20:04:24 2017
Thread-1: Wed Sep 27 20:04:24 2017
Thread-1: Wed Sep 27 20:04:25 2017
Exiting Thread-1
Thread-2: Wed Sep 27 20:04:26 2017
Thread-2: Wed Sep 27 20:04:28 2017
Thread-2: Wed Sep 27 20:04:30 2017
Exiting Thread-2
Exiting Main Thread
互斥鎖同步執行緒
不加鎖的問題
當不同的執行緒操作同一批資料的時候,就有可能產生意想不到的問題。比如說:
# encoding: UTF-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
num = num+1
msg = self.name+' set num to '+str(num)
print msg
num = 0
threads = []
def test():
for i in range(1000):
t = MyThread()
t.start()
threads.append(t)
if __name__ == '__main__':
test()
for t in threads:
t.join()
print num
理論上說,一千個執行緒都讓num增1,結果應該是1000,但是輸出的結果不是1000:(而且每次都不一樣)
............
Thread-998 set num to 905
Thread-988 set num to 906
Thread-994 set num to 904
Thread-992 set num to 901
Thread-990 set num to 907
Thread-1000 set num to 908
908
這是因為不同執行緒同時操作同樣資料導致的執行緒不同步。此時需要通過加互斥鎖實現執行緒的同步。
加鎖的效果
# encoding: UTF-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
threadLock.acquire()
num = num+1
threadLock.release()
msg = self.name+' set num to '+str(num)
print msg
num = 0
threadLock = threading.Lock()
threads = []
def test():
for i in range(1000):
t = MyThread()
t.start()
threads.append(t)
if __name__ == '__main__':
test()
for t in threads:
t.join()
print num
加鎖相當於每個資料在每一時刻只能被一個執行緒獲取到,而獲取不到鎖的執行緒就會處於暫時的阻塞狀態。輸出結果是這樣的:
.........
Thread-994 set num to 994
Thread-995 set num to 995
Thread-993 set num to 993
Thread-996 set num to 996
Thread-999 set num to 997
Thread-1000 set num to 998
Thread-998 set num to 999
Thread-997 set num to 1000
1000
可以看出,並不是按照執行緒的建立時間獲取資料的處理許可權,但是結果卻可以保證每個執行緒都能依次處理資料,從而保證資料被自增了1000次。