6、多线程

创建线程

由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。

Python的标准库提供了两个模块:_threadthreading_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

创建线程的语法:

t = threading.Thread()

常用参数:

name:线程名,如果不起名字Python就自动给线程命名为Thread-1Thread-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()

threading

Thread

Lock

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。

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)