热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python系统学习第二十五课

共享变量当多个线程同时访问同一个变量的时候,会产生共享变量的问题解决变量锁,信号灯锁(Lock):是一个标志,
共享变量
  • 当多个线程同时访问同一个变量的时候,会产生共享变量的问题
  • 解决变量
    • 锁,信号灯
    • 锁(Lock):
      • 是一个标志,表示一个线程在占用一些资源
      • 使用方法
        • 上锁
        • 使用共享资源,放心使用
        • 取消锁,释放锁
      • 锁谁:哪个资源需要多个线程共享,锁哪个
      • 理解锁:锁其实不是锁住谁,而是一个令牌
    • 线程安全问题:
      • 如果一个变量/资源,他对于多线程来讲,不用加锁也不会引起任何问题,则成为线程安全
      • 线程不安全变量类型:list, set, dict
      • 线程安全变量类型:queue
    • 生产者消费者问题
      • 一个模型,可以用来搭建消息队列
      • queue是一个用来存放变量的数据结构,特点是先进先出,内部元素排队,可以理解成一个特殊的list

#每次执行都产生不同的值
import threadingsum = 0
loopSum = 1000000def myAdd():global sum, loopSumfor i in range(1, loopSum):sum += 1def myMinu():global sum, loopSumfor i in range(1, loopSum):sum -= 1if __name__ == '__main__':print("Starting ....{0}".format(sum))# 开始多线程的实例,看执行结果是否一样t1 = threading.Thread(target=myAdd, args=())t2 = threading.Thread(target=myMinu, args=())t1.start()t2.start()t1.join()t2.join()print("Done .... {0}".format(sum))

Starting ....0
Done .... -11539

import threadingsum = 0
loopSum = 1000000lock = threading.Lock()def myAdd():global sum, loopSumfor i in range(1, loopSum):# 上锁,申请锁lock.acquire()sum += 1# 释放锁lock.release()def myMinu():global sum, loopSumfor i in range(1, loopSum):lock.acquire()sum -= 1lock.release()if __name__ == '__main__':print("Starting ....{0}".format(sum))# 开始多线程的实例,看执行结果是否一样t1 = threading.Thread(target=myAdd, args=())t2 = threading.Thread(target=myMinu, args=())t1.start()t2.start()t1.join()t2.join()print("Done .... {0}".format(sum))

Starting ....0
Done .... 0

#生产者消费者模型
import threading
import time# Python2
# from Queue import Queue# Python3
import queueclass Producer(threading.Thread):def run(self):global queuecount &#61; 0while True:# qsize返回queue内容长度if queue.qsize() < 1000:for i in range(100):count &#61; count &#43;1msg &#61; &#39;生成产品&#39;&#43;str(count)# put是网queue中放入一个值queue.put(msg)print(msg)time.sleep(0.5)class Consumer(threading.Thread):def run(self):global queuewhile True:if queue.qsize() > 100:for i in range(3):# get是从queue中取出一个值msg &#61; self.name &#43; &#39;消费了 &#39;&#43;queue.get()print(msg)time.sleep(1)if __name__ &#61;&#61; &#39;__main__&#39;:queue &#61; queue.Queue()for i in range(500):queue.put(&#39;初始产品&#39;&#43;str(i))for i in range(2):p &#61; Producer() #两个生产者p.start()for i in range(5): #五个消费者c &#61; Consumer()c.start()

  • 死锁问题

#死锁案例
import threading
import timelock_1 &#61; threading.Lock()
lock_2 &#61; threading.Lock()def func_1():print("func_1 starting.........")lock_1.acquire()print("func_1 申请了 lock_1....")time.sleep(2)print("func_1 等待 lock_2.......")lock_2.acquire()print("func_1 申请了 lock_2.......")lock_2.release()print("func_1 释放了 lock_2")lock_1.release()print("func_1 释放了 lock_1")print("func_1 done..........")def func_2():print("func_2 starting.........")lock_2.acquire()print("func_2 申请了 lock_2....")time.sleep(4)print("func_2 等待 lock_1.......")lock_1.acquire()print("func_2 申请了 lock_1.......")lock_1.release()print("func_2 释放了 lock_1")lock_2.release()print("func_2 释放了 lock_2")print("func_2 done..........")if __name__ &#61;&#61; "__main__":print("主程序启动..............")t1 &#61; threading.Thread(target&#61;func_1, args&#61;())t2 &#61; threading.Thread(target&#61;func_2, args&#61;())t1.start()t2.start()
# 锁1先醒了之后&#xff0c;等待锁2 的醒来&#xff0c;但是&#xff0c;锁2 一直在函数2中沉睡&#xff0c;所以就是说&#xff0c;没有释放锁2。形成死锁&#xff0c;所以使用的时候要注意t1.join()t2.join()print("主程序启动..............")

主程序启动..............
func_1 starting.........
func_2 starting.........
func_2 申请了 lock_2....
func_1 申请了 lock_1....
func_1 等待 lock_2.......
func_2 等待 lock_1.......

# 锁的等待时间问题import threading
import timelock_1 &#61; threading.Lock()
lock_2 &#61; threading.Lock()def func_1():print("func_1 starting.........")lock_1.acquire(timeout&#61;4) #超时时间&#xff0c;等待时间是四秒&#xff0c;不能超过四秒print("func_1 申请了 lock_1....")time.sleep(2)print("func_1 等待 lock_2.......")rst &#61; lock_2.acquire(timeout&#61;2)if rst:print("func_1 已经得到锁 lock_2")lock_2.release()print("func_1 释放了锁 lock_2")else:print("func_1 注定没申请到lock_2.....")lock_1.release()print("func_1 释放了 lock_1")print("func_1 done..........")def func_2():print("func_2 starting.........")lock_2.acquire()print("func_2 申请了 lock_2....")time.sleep(4)print("func_2 等待 lock_1.......")lock_1.acquire()print("func_2 申请了 lock_1.......")lock_1.release()print("func_2 释放了 lock_1")lock_2.release()print("func_2 释放了 lock_2")print("func_2 done..........")if __name__ &#61;&#61; "__main__":print("主程序启动..............")t1 &#61; threading.Thread(target&#61;func_1, args&#61;())t2 &#61; threading.Thread(target&#61;func_2, args&#61;())t1.start()t2.start()t1.join()t2.join()print("主程序结束..............")

  • semphore
    • 允许一个资源由多个线程使用

import threading
import time# 参数定义最多几个线程同时使用资源
semaphore &#61; threading.Semaphore(3)def func():if semaphore.acquire():for i in range(5):print(threading.currentThread().getName() &#43; &#39; get semaphore&#39;)time.sleep(15)semaphore.release()print(threading.currentThread().getName() &#43; &#39; release semaphore&#39;)for i in range(8):t1 &#61; threading.Thread(target&#61;func)t1.start()

  • threading.Timer
    • timer是利用多线程&#xff0c;在指定时间后启动一个功能

#案例
import threading
import timedef func():print("I am running.........")time.sleep(4)print("I am done......")if __name__ &#61;&#61; "__main__":t &#61; threading.Timer(6, func)t.start()i &#61; 0while True:print("{0}***************".format(i))time.sleep(3)i &#43;&#61; 1

  • 可重入锁
    • 一个锁&#xff0c;可以被一个线程多次申请
    • 主要解决递归调用的时候&#xff0c;需要申请锁的情况

import threading
import timeclass MyThread(threading.Thread):def run(self):global numtime.sleep(1)if mutex.acquire(1):num &#61; num&#43;1msg &#61; self.name&#43;&#39; set num to &#39;&#43;str(num)print(msg)mutex.acquire()mutex.release()mutex.release()num &#61; 0mutex &#61; threading.RLock()def testTh():for i in range(5):t &#61; MyThread()t.start()if __name__ &#61;&#61; &#39;__main__&#39;:testTh()


推荐阅读
  • RingBuffer,或者说CircularBuffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • Python中的PyInputPlus模块原文:https ... [详细]
  • python+selenium十:基于原生selenium的二次封装fromseleniumimportwebdriverfromselenium.webdriv ... [详细]
  • [翻译]PyCairo指南裁剪和masking
    裁剪和masking在PyCairo指南的这个部分,我么将讨论裁剪和masking操作。裁剪裁剪就是将图形的绘制限定在一定的区域内。这样做有一些效率的因素࿰ ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • 一、什么是闭包?有什么作用什么是闭包闭包是定义在一个函数内部的函数,它可以访问父级函数的内部变量。当一个闭包被创建时,会关联一个作用域—— ... [详细]
  • 广度优先遍历(BFS)算法的概述、代码实现和应用
    本文介绍了广度优先遍历(BFS)算法的概述、邻接矩阵和邻接表的代码实现,并讨论了BFS在求解最短路径或最短步数问题上的应用。以LeetCode中的934.最短的桥为例,详细阐述了BFS的具体思路和代码实现。最后,推荐了一些相关的BFS算法题目供大家练习。 ... [详细]
  • C++ STL复习(13)容器适配器
    STL提供了3种容器适配器,分别为stack栈适配器、queue队列适配器以及priority_queue优先权队列适配器。不同场景下,由于不同的序列式 ... [详细]
  • QuestionThereareatotalofncoursesyouhavetotake,labeledfrom0ton-1.Somecoursesmayhaveprerequi ... [详细]
author-avatar
天蝎丿冷傲丨
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有