一. 线程和进程的概念
进程是操作系统中正在执行的不同应用程序的一个实例
线程是进程中的一个实体,是被操作系统独立调度和分派处理器时间的基本单位
线程的优缺点
并发处理,因而特别适合需要同时执行多个操作的场合
解决用户响应性能和多任务的问题
引入了资源共享和同步等问题
协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程更类似于函数调用
Python的asyncio模块实现的异步IO编程框架中,协程是对使用async关键字定义的异步函数的调用
一个进程包含多个线程,同样,一个程序可以包含多个协程。多个线程相对独立,线程有自己的上下文,切换受系统控制;同样,多个协程也相对独立,协程也有自己的上下文,但是其切换由程序自己控制。
协程适合于异步IO编程的场合,能有效提高IO的吞吐效率。
通过thread派生类的方法,直接调用
import threading, time, random
class MyThread(threading.Thread): # 继承threading.Thread
def __init__(self): # 构造函数
threading.Thread.__init__(self) # 调用父类构造函数
def run(self): # 定义run方法
for i in range(5):
time.sleep(1) # 睡眠1秒
t = threading.current_thread() # 获取当前线程
print('{0} at {1}\n'.format(t.name, time.strftime("%H:%M:%S",time.localtime()))) # 打印线程名、当前时间
print('线程t1结束')
def test():
t1 = MyThread() # 创建线程对象
t1.name = 't1' # 设置线程名称
t1.start() # 启动线程
print('主线程开始等待线程(t1)2s');
t1.join(5)
print("当前线程总数:", threading.active_count())
print('主线程等待线程(t1)5s结束')
print('主线程开始等待线程结束');
t1.join()
print("当前线程总数:", threading.enumerate())
print('主线程结束')
if __name__ == '__main__':
test()
timer线程
使用Python标准库threading中的Timer线程(Thread的子类),可以很方便实现定时器功能。Timer对象包含的主要方法如下:
(1)Timer(interval, function, args=None, kwargs=None):构造函数。在指定时间interval后执行函数
(2)start():启动线程,即启动计时器
(3)cancel():取消计时器
原语锁lock的理解
银行现金帐户取款。多个线程同时执行取款操作时,如果不使用同步处理,会造成账户余额混乱;尝试使用同步锁对象Lock,以保证多个线程同时执行取款操作时,银行现金帐户取款的有效和一致
如果将同步锁去除
银行多线程同步取款
import threading, time, random
class Account(threading.Thread): # 继承threading.Thread
lock = threading.Lock() # 创建锁
def __init__(self, amount): # 构造函数
threading.Thread.__init__(self) # 调用父类构造函数
Account.amount = amount # 账户金额
def run(self): # 定义run方法
self.withdraw() # 取款
def withdraw(self):
Account.lock.acquire() # 获取锁。注释不使用同步处理
t = threading.current_thread()
a = random.choice(range(50, 101))
if Account.amount < a:
print('{0}交易失败。取款前余额:{1},取款额:{2}'.format(t.name, Account.amount, a))
Account.lock.release()
return 0 # 拒绝交易
time.sleep(random.choice(range(5))) # 随机睡眠[0-5)秒
prev = Account.amount
Account.amount -= a # 取款
print('{0}取款前余额:{1}, 取款额:{2}, 取款后额:{3}'.format(t.name, prev, a, Account.amount))
Account.lock.release() # 释放锁。注释不使用同步处理
def test():
for i in range(5): # 创建5个线程对象并启动
Account(200).start()
if __name__ == '__main__':
test()
import threading
from random import randint
from time import sleep
# 自定义线程生产类
class Producer(threading.Thread):
def __init__(self, threadname):
threading.Thread.__init__(self, name=threadname)
def run(self):
global x
while True:
sleep(2)
# 获取锁
con.acquire()
# 假设共享列表中最多能容纳5个元素
if len(x) == 5:
# 如果共享列表已满,生产者等待
print("生产者等待......")
con.wait()
else:
r = randint(1, 1000)
print('Produced:', r)
# 产生新元素,添加之共享列表
x.append(r)
# 唤醒等待条件线程
con.notify()
# 释放锁
con.release()
# 自定义消费者线程
class Consumer(threading.Thread):
def __init__(self, threadname):
threading.Thread.__init__(self, name=threadname)
def run(self):
global x
while True:
sleep(3)
# 获取锁
con.acquire()
if not x:
# 等待
print('消费者在等待......')
con.wait()
else:
# pop()删列表里面的第一个元素
print("consumed:", x.pop(0))
con.notify()
# 释放锁
con.release()
if __name__ == '__main__':
con = threading.Condition()
x = []
p = Producer('Producer')
c = Consumer('Consumer')
p.start()
c.start()