由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。
Python的标准库提供了两个模块:_thread
和threading
,_thread
是低级模块,threading
是高级模块,对_thread
进行了封装。绝大多数情况下,我们只需要使用threading
这个高级模块。
创建线程的语法:
t = threading.Thread()
常用参数:
name
:线程名,如果不起名字Python就自动给线程命名为Thread-1
,Thread-2
target
:线程执行的函数
args
:传递给线程函数的参数,必须是个tuple元组类型
import time, threading
def printCount(sec):
print('线程 %s 正在运行...' % threading.current_thread().name)
n = 0
while n < 5:
n += 1
print('线程 %s >>> %s' % (threading.current_thread().name,n))
# 推迟线程的调用sec秒
time.sleep(sec)
print('线程 %s 结束运行...' % threading.current_thread().name)
t1 = threading.Thread(name='printConut1',target=printCount,args=(1,))
t2 = threading.Thread(name='printConut2',target=printCount,args=(3,))
t1.start()
t2.start()
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
import threading
count = 0
# 每次调用先+8、后-8,结果应该是0
def addCount():
global count
count = count + 8
count = count - 8
def threadRun():
for i in range(2000000):
addCount()
t1 = threading.Thread(target=threadRun)
t2 = threading.Thread(target=threadRun)
t1.start()
t2.start()
t1.join()
t2.join()
#此时的count不是0
print(count)
使用同步锁,由于锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。创建一个锁就是通过threading.Lock()
来实现
当多个线程同时执行lock.acquire()
时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。
获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally
来确保锁一定会被释放。
threading.Lock().acquire()
:获得锁
threading.Lock().release()
:释放锁
import threading
lock = threading.Lock()
count = 0
# 每次调用先+8、后-8,结果应该是0
def addCount():
#加锁
lock.acquire()
global count
try:
count = count + 8
count = count - 8
finally:
#释放锁
lock.release()
def threadRun():
for i in range(2000000):
addCount()
t1 = threading.Thread(target=threadRun)
t2 = threading.Thread(target=threadRun)
t1.start()
t2.start()
t1.join()
t2.join()
#此时的count不是0
print(count)