我们的目标是:通过这一套资料学习下来,可以熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。
上篇文章我们讨论了通过创建线程的相关知识。今天学习一下线程间通信的相关知识。
1、线程间可以直接共享信息吗?
我们在之前的章节中学习了进程,并且知道进程之间不能直接共享信息。可以使用队列来进行进程之间的通信。那线程之间能够之间共享信息吗?答案是可以。
举例说明:
import threading
#创建两个线程分别对全局变量进行操作,检查结果,确认线程间能之间共享信息
def plus(): #加法
print("**********子线程加法开始************")
global test_number
test_number +=100
print("test_number +100 is %d"%test_number)
print("**********子线程加法结束************")
def minus():
print("**********子线程减法开始************")
global test_number
test_number -= 100
print("test_number -100 is %d" % test_number)
print("**********子线程减法结束************")
test_number = 200 #定义一个全局变量
def main():
print("*************主线程开始***************")
print("test_number is %d"%test_number) #测试值开始的值为200
thread1 = threading.Thread(target=plus) #使用测试值加100
thread2 = threading.Thread(target=minus)
thread1.start() #子线程启动
thread2.start()
thread1.join() #等待子线程结束
thread2.join()
print("*************主线程结束***************")
if __name__=="__main__":
main()
输出结果参考:
2、互斥锁
1)互斥锁的简介
上面我们举例说明了,线程是可以对全局变量进行随意修改。这样也就可能造成多线程之间对全局变量的混乱。如何解决这一问题呢?例如大家都排队上厕所,一种防止他人进入房间的简单方法就是进门后就上锁,后面的人就只能继续等待。
在程序中叫互斥锁(mutual exclusion 缩写为Mutex),防止多个线程同时读写某一块内存区域。互斥锁为资源引入一个状态,即锁定或者非锁定。某个线程要更改共享数据时,先将其锁定。
2)使用互斥锁
在threading 模块中使用lock 类可以方便的处理锁定。lock 类有两个方法,即acquire()锁定和release()释放锁。用法如下:
mutex = threading.Lock() #创建锁
mutex.acquire([blocking]) #锁定
mutex.release() #释放锁
参数说明:
acquire([blocking])----获取锁定,如果有必要,则需要阻塞到锁定被释放位置。若是提供blocking 参数并将它设置为False:当无法获取锁定时将立即返回False;当成功获取锁定时,将返回True.
release()------释放一个锁定,当锁处于未锁定状态时,或者从原本调用acquire()方法的不同线程中调用此方法,将会出现错误。
举例说明:
#使用互斥锁实现多人同时订购火车票的功能
#如某车次有100张票,10个人同时抢购,每售出一张,显示一次剩余火车票数量。
ticket_number = 100
mutex = Lock() #实例化lock 类
def task():
global ticket_number
mutex.acquire()
temp = ticket_number
time.sleep(0.2)
ticket_number = temp -1
print("购买成功,剩余%d张火车票"%ticket_number)
mutex.release()
def main():
thread_L = [] #初始化一个列表
for i in range(10):
thread = Thread(target=task) #实例化线程类,创建线程
thread_L.append(thread) #将线程实例存入列表中
thread.start() #启动线程
for thread in thread_L:
thread.join() #等待子线程结束
if __name__=="__main__":
main()
输出参考:
购买成功,剩余99张火车票
购买成功,剩余98张火车票
购买成功,剩余97张火车票
购买成功,剩余96张火车票
购买成功,剩余95张火车票
购买成功,剩余94张火车票
购买成功,剩余93张火车票
购买成功,剩余92张火车票
购买成功,剩余91张火车票
购买成功,剩余90张火车票
Process finished with exit code 0
上述代码中创建了10个线程,全部执行task()函数。为解决资源竞争问题,使用mutex.acquire()函数实现资源锁定。每次只有一个线程执行task()函数。
3、线程间通信-by queue
我们已经直到multiprocessing 模块的Queue 队列可以实现进程间通信,同样在线程间也可以使用Queue 队列进行通信。不同之处在于需要使用queue 中Queue 队列,而不是multiprocessing 模块的Queue 队列。但是,两者的Queue 队列使用的方法相同。
举例说明:
#使用队列模式模拟生产者和消费者,定义一个生产者类Producer 和一个消费者类Consumer.
#生产者共生产5件商品,并将5件商品依次写入队列中,而消费者依次从队列中取出产品
#生产者类
class Producer(threading.Thread):
def __init__(self,name,queue):
threading.Thread.__init__(self,name=name)
self.data = queue
def run(self):
for i in range(5):
print("生产者%s将产品%d加入队列!"%(self.name,i))
self.data.put(i)
time.sleep(random())
print("生产者%s完成!"%self.name)
#消费者类,子线程类
class Consumer(threading.Thread):
def __init__(self,name,queue):
threading.Thread.__init__(self, name=name)
self.data = queue
def run(self):
for i in range(5):
val = self.data.get() #取出队列中数据
print("消费者%s将产品%d从队列中取出!" % (self.name, val))
time.sleep(random())
print("消费者%s完成!"%self.name)
def main():
print("-----------主线程开始-----------")
queue = Queue() #实例化队列
producer = Producer("Producer",queue) #实例化线程producer,并将其传入队列中作为参数,子线程
consumer = Consumer("Consumer",queue)
producer.start() #线程启动
consumer.start()
producer.join() #等待子线程结束
consumer.join()
print("-----------主线程结束-----------")
if __name__=="__main__":
main()
输出结果参考:
-------------------------------------------------------------------------------------------------------------------
-----------主线程开始-----------
生产者Producer将产品0加入队列!
消费者Consumer将产品0从队列中取出!
生产者Producer将产品1加入队列!
消费者Consumer将产品1从队列中取出!
生产者Producer将产品2加入队列!
消费者Consumer将产品2从队列中取出!
生产者Producer将产品3加入队列!
消费者Consumer将产品3从队列中取出!
生产者Producer将产品4加入队列!
生产者Producer完成!
消费者Consumer将产品4从队列中取出!
消费者Consumer完成!
-----------主线程结束-----------
Process finished with exit code 0
-------------------------------------------------------------------------------------------------------------------
今天先写学习到这里了,每天进步一点点。明天也要加油啊!