python theading线程开发与加锁、信号量、事件等详解

时间:2021-12-17 00:14:21

线程有2种调用方式,如下:

直接调用

 import threading
import time

def sayhi(num): #定义每个线程要运行的函数
print("running on number:%s" %num)
time.sleep(3) if __name__ == '__main__':
t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
t1.start() #启动线程
t2.start() #启动另一个线程
print(t1.getName()) #获取线程名
print(t2.getName())

继承式调用

import threading
import time

class MyThread(threading.Thread):
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num def run(self):#定义每个线程要运行的函数
print("running on number:%s" %self.num)
time.sleep(3) if __name__ == '__main__':
t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()

同步锁(py2版本) *注:不要在3.x上运行,不知为什么,3.x上的结果总是正确的,可能是自动加了锁

 import time
import threading def addNum():
global num # 在每个线程中都获取这个全局变量
print('--get num: %s' %num)
time.sleep(1)
lock.acquire() # 修改数据前加锁
num -= 1 # 对此公共变量进行-1操作
lock.release() # 修改后释放 num = 100 # 设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
print "threading num: %s \n" %threading.active_count() #查看线程数
thread_list.append(t) for t in thread_list: # 等待所有线程执行完毕
t.join() print('final num:', num)

死锁

所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程成为死锁进程。

 import threading
import time mutexA = threading.Lock()
mutexB = threading.Lock() class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) def run(self):
self.fun1()
self.fun2() def fun1(self):
mutexA.acquire()
print("fun1 I am %s,get res:%s---%s" % (self.name, "ResA", time.time())) mutexB.acquire()#线程2卡在这里,获取不到锁B,线程2此时已经有锁A
print("fun1 I am %s,get res:%s---%s" % (self.name, "ResB", time.time()))
mutexB.release()
print("FUN1 I am %s, release res:%s---%s" % (self.name, "ResB", time.time()))
mutexA.release()
print("FUN1 I am %s, release res:%s---%s" % (self.name, "ResA", time.time())) def fun2(self):
mutexB.acquire()
print("fun2 I am %s,get res:%s---%s" % (self.name, "ResB", time.time())) time.sleep(0.3) #这里整个进程sleep,
print("sleep fun2 I am %s,get res:%s---%s" % (self.name, "ResB", time.time())) mutexA.acquire()#线程1卡在这一步,线程1此时已经有锁b
print("fun2 I am %s,get res:%s---%s" % (self.name, "ResA", time.time())) mutexA.release()
print("FUN1 I am %s, release res:%s---%s" % (self.name, "ResA", time.time())) mutexB.release()
print("FUN1 I am %s, release res:%s---%s" % (self.name, "ResB", time.time())) if __name__ == '__main__':
print("start------------%s", time.time())
for i in range(0, 10): #一次循环,代表一个线程
print "%s \n" %i
my_thread = MyThread()
my_thread.start()
运行结果

0

fun1 I am Thread-1,get res:ResA---1551263063.35       #线程1获得锁B
fun1 I am Thread-1,get res:ResB---1551263063.35       #线程1获得锁B
FUN1 I am Thread-1, release res:ResB---1551263063.35  #线程1释放锁B
FUN1 I am Thread-1, release res:ResA---1551263063.35  #线程1释放锁A
fun2 I am Thread-1,get res:ResB---1551263063.35       #线程1获得锁B

1

fun1 I am Thread-2,get res:ResA---1551263063.35       #线程2释放锁A

2

..

9

sleep fun2 I am Thread-1,get res:ResB---1551263065.35 #线程2释放锁B

总结:

1、线程1已有B锁,准备获取A锁

2、线程2已有A锁,准备获取B锁

1和2同一时刻,因此互相等待

RLock(递归锁)

说白了就是在一个大锁中还要再包含子锁

在python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

 Rlock = threading.RLock()
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) def run(self):
self.fun1()
self.fun2() def fun1(self):
Rlock.acquire() # 如果锁被占用,则阻塞在这里,等待锁的释放
print("I am %s,get res:%s---%s" % (self.name, "ResA", time.time()))
Rlock.acquire() # count=2
print("I am %s,get res:%s---%s" % (self.name, "ResB", time.time())) Rlock.release() # count-1
Rlock.release() # count-1=0 def fun2(self):
Rlock.acquire() # count=1
print("I am %s,get res:%s---%s" % (self.name, "ResB", time.time()))
time.sleep(0.2) Rlock.acquire() # count=2
print("I am %s,get res:%s---%s" % (self.name, "ResA", time.time()))
Rlock.release() # coun-1
Rlock.release() # count-1 if __name__ == '__main__':
print("start-----------%s" % time.time())
for i in range(0, 10):
my_thread = MyThread()
my_thread.start()

Semaphore(信号量)

原理:来限制一个时间点内的线程数量。比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

 def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s\n" %n)
semaphore.release() if __name__ == '__main__':
num= 0
semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run,args=(i,))
t.start() while threading.active_count() != 1:
pass #print threading.active_count()
else:
print('----all threads done---')
print(num)

Events

通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。

红绿灯

 import threading,time
import random
def light():
if not event.isSet():
event.set() #wait就不阻塞 #绿灯状态
count = 0
while True:
if count < 10:
print('\033[42;1m--green light on---\033[0m')
elif count <13:
print('\033[43;1m--yellow light on---\033[0m')
elif count <20:
if event.isSet():
event.clear()
print('\033[41;1m--red light on---\033[0m')
else:
count = 0
event.set() #打开绿灯
time.sleep(1)
count +=1
def car(n):
while 1:
time.sleep(random.randrange(10))
if event.isSet(): #绿灯
print("car [%s] is running.." % n)
else:
print("car [%s] is waiting for the red light.." %n)
if __name__ == '__main__':
event = threading.Event()
Light = threading.Thread(target=light)
Light.start()
for i in range(3):
t = threading.Thread(target=car,args=(i,))
t.start()

员工过门禁

 import threading
import time
import random def door():
door_open_time_counter = 0
while True:
if door_swiping_event.is_set():
print("\033[32;1mdoor opening....\033[0m")
door_open_time_counter +=1
else:
print("\033[31;1mdoor closed....,please swipe to open.\033[0m")
door_open_time_counter = 0 #清空计时器
door_swiping_event.wait()
if door_open_time_counter > 3:#门开了已经3s了,该关了
door_swiping_event.clear()
time.sleep(0.5) def staff(n):
print("staff [%s] is comming..." % n )
while True:
if door_swiping_event.is_set():
print("\033[34;1mdoor is opened, staff [%s] passing.....over!!\033[0m" % n )
break
else:
print("STAFF [%s] sees door got closed, swipping the card....." % n)
door_swiping_event.set()
print("after set,,, staff [%s]--------" %n,door_swiping_event.is_set())
# time.sleep(0.5) door_swiping_event = threading.Event() #设置事件
door_thread = threading.Thread(target=door)
door_thread.start()
for i in range(5):
p = threading.Thread(target=staff,args=(i,))
time.sleep(random.randrange(3))
p.start()
运行结果
door closed....,please swipe to open.
staff [0] is comming...
STAFF [0] sees door got closed, swipping the card.....
('after set,,, staff [0]--------', True)
door is opened, staff [0] passing.....over!!
door opening....
door opening....
door opening....
door opening....
staff [1] is comming...
STAFF [1] sees door got closed, swipping the card.....
('after set,,, staff [1]--------'staff [2] is comming...,
Truedoor is opened, staff [2] passing.....over!!) door is opened, staff [1] passing.....over!!
door opening....
door closed....,please swipe to open.
staff [3] is comming...
STAFF [3] sees door got closed, swipping the card.....
('after set,,, staff [3]--------', True)
door is opened, staff [3] passing.....over!!
door opening....
door opening....
staff [4] is comming...
door is opened, staff [4] passing.....over!!
door opening....
door opening....
door closed....,please swipe to open.

python theading线程开发与加锁、信号量、事件等详解的更多相关文章

  1. &lbrack; 转载 &rsqb; Java开发中的23种设计模式详解&lpar;转&rpar;

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  2. python中日志logging模块的性能及多进程详解

    python中日志logging模块的性能及多进程详解 使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和分析.Python的 ...

  3. Java线程通讯方法之wait&lpar;&rpar;、nofity&lpar;&rpar; 详解

    Java线程通讯方法之wait().nofity() 详解 本文将探讨以下问题: synchronized 代码块使用 notify()与notifyAll()的区别 Java wait(),noti ...

  4. jQuery 事件用法详解

    jQuery 事件用法详解 目录 简介 实现原理 事件操作 绑定事件 解除事件 触发事件 事件委托 事件操作进阶 阻止默认事件 阻止事件传播 阻止事件向后执行 命名空间 自定义事件 事件队列 jque ...

  5. cocos2dx&plus;lua注册事件函数详解

    coocs2dx 版本 3.1.1 registerScriptTouchHandler 注册触屏事件 registerScriptTapHandler 注册点击事件 registerScriptHa ...

  6. 最锋利的Visual Studio Web开发工具扩展:Web Essentials详解

    原文:最锋利的Visual Studio Web开发工具扩展:Web Essentials详解 Web Essentials是目前为止见过的最好用的VS扩展工具了,具体功能请待我一一道来. 首先,从E ...

  7. cocos2dx&plus;lua注册事件函数详解 事件

    coocs2dx 版本 3.1.1 registerScriptTouchHandler             注册触屏事件 registerScriptTapHandler             ...

  8. &lpar;转载&rpar;【cocos2dx 3&period;x Lua&rsqb; 注册事件函数详解

    出处: http://www.2cto.com/kf/201409/338235.html coocs2dx 版本 3.1.1 registerScriptTouchHandler 注册触屏事件 re ...

  9. 委托与事件代码详解与(Object sender&comma;EventArgs e)详解

    委托与事件代码详解 using System;using System.Collections.Generic;using System.Text; namespace @Delegate //自定义 ...

随机推荐

  1. SAP SMARTFORM 记录实际打印次数

    http://blog.csdn.net/wangjolly/article/details/8334008

  2. 用户体验学习笔记(工程中发现的PM常犯错误)

    清晰呈现 启动和停止 布局 导航 层级式 扁平式 内容/体验主导式 总结 动画 注意点 品牌化 当你需要在 app 中提醒用户品牌的存在时,请遵循以下准则: 以优雅谦逊的方式整合品牌资产.人们使用你的 ...

  3. &lbrack;蓝牙&rsqb; 5、Battery Service module

    Detailed Description This module implements the Battery Service with the Battery Level characteristi ...

  4. 基于MATLAB的离散小波变换

    申明,本文非笔者原创,原文转载自:  基于Matlab的离散小波变换         http://blog.sina.com.cn/s/blog_725866260100ryh3.html 简介 在 ...

  5. JavaScript高级程序设计 读书笔记

    第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...

  6. TSP问题&lbrack;动态规划&rsqb;

    分析: 有用的量:城市集合V={a,b,c,d,--} 所以我们用 T(i,V) 表示从 城市 i 出发遍历集合 V 中的城市一遍且仅一遍后回到 i 所用的最少费用(这里可能表达不好,底下会看到,但是 ...

  7. Web前端知识体系精简

    Web前端技术由html.css和javascript三大部分构成,是一个庞大而复杂的技术体系,其复杂程度不低于任何一门后端语言.而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学习新的知 ...

  8. JavaScript基础教程2-20160612

    1.JavaScript之操作html元素,Dom Dom是抽象出来的网页对象,需要了解面向对象的思想:调用对象下的方法实现相应的功能 使用JS调用dom来创建标签. //document是网页对象 ...

  9. java之路 定义个一初始值 取它 个位 十位 百位 千位。。的数值。

    class Demo{ public static void main(String[] args){ int i =2584; //do{ int g = i%10; int s = (i%100) ...

  10. &lbrack;CXF REST标准实战系列&rsqb; 二、Spring4&period;0 整合 CXF3&period;0&comma;实现测试接口

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章Points: 1.介绍RESTful架构 ...