python中的线程锁
锁对象
原始锁是一个在锁定时不属于特定线程的同步基元组件。在Python中,它是能用的最低级的同步基元组件,由 _thread
扩展模块直接实现。
原始锁处于 "锁定" 或者 "非锁定" 两种状态之一。它被创建时为非锁定状态。它有两个基本方法, acquire()
和 release()
。当状态为非锁定时, acquire()
将状态改为 锁定 并立即返回。当状态是锁定时, acquire()
将阻塞至其他线程调用 release()
将其改为非锁定状态,然后 acquire()
调用重置其为锁定状态并返回。 release()
只在锁定状态下调用; 它将状态改为非锁定并立即返回。如果尝试释放一个非锁定的锁,则会引发 RuntimeError
异常。
锁同样支持 上下文管理协议。
当多个线程在 acquire()
等待状态转变为未锁定被阻塞,然后 release()
重置状态为未锁定时,只有一个线程能继续执行;至于哪个等待线程继续执行没有定义,并且会根据实现而不同。
acquire
(blocking=True, timeout=-1)可以阻塞或非阻塞地获得锁。当调用时参数 blocking 设置为 True
(缺省值),阻塞直到锁被释放,然后将锁锁定并返回 True
。在参数 blocking 被设置为 False
的情况下调用,将不会发生阻塞。如果调用时 blocking 设为 True
会阻塞,并立即返回 False
;否则,将锁锁定并返回 True
。当浮点型 timeout 参数被设置为正值调用时,只要无法获得锁,将最多阻塞 timeout 设定的秒数。timeout 参数被设置为 -1
时将无限等待。当 blocking 为 false 时,timeout 指定的值将被忽略。如果成功获得锁,则返回 True
,否则返回 False
(例如发生 超时 的时候)。
release
()
- 释放一个锁。这个方法可以在任何线程中调用,不单指获得锁的线程。当锁被锁定,将它重置为未锁定,并返回。如果其他线程正在等待这个锁解锁而被阻塞,只允许其中一个允许。在未锁定的锁调用时,会引发
RuntimeError
异常。没有返回值。递归锁对象
重入锁是一个可以被同一个线程多次获取的同步基元组件。在内部,它在基元锁的锁定/非锁定状态上附加了 "所属线程" 和 "递归等级" 的概念。在锁定状态下,某些线程拥有锁 ; 在非锁定状态下, 没有线程拥有它。
若要锁定锁,线程调用其
acquire()
方法;一旦线程拥有了锁,方法将返回。若要解锁,线程调用release()
方法。acquire()
/release()
对可以嵌套;只有最终release()
(最外面一对的release()
) 将锁解开,才能让其他线程继续处理acquire()
阻塞。递归锁也支持 上下文管理协议。
条件对象
条件变量总是与某种类型的锁对象相关联,锁对象可以通过传入获得,或者在缺省的情况下自动创建。当多个条件变量需要共享同一个锁时,传入一个锁很有用。锁是条件对象的一部分,你不必单独地跟踪它。
条件变量服从 上下文管理协议:使用
with
语句会在它包围的代码块内获取关联的锁。acquire()
和release()
方法也能调用关联锁的相关方法。其它方法必须在持有关联的锁的情况下调用。
wait()
方法释放锁,然后阻塞直到其它线程调用notify()
方法或notify_all()
方法唤醒它。一旦被唤醒,wait()
方法重新获取锁并返回。它也可以指定超时时间。The
notify()
method wakes up one of the threads waiting for the condition variable, if any are waiting. Thenotify_all()
method wakes up all threads waiting for the condition variable.注意:
notify()
方法和notify_all()
方法并不会释放锁,这意味着被唤醒的线程不会立即从它们的wait()
方法调用中返回,而是会在调用了notify()
方法或notify_all()
方法的线程最终放弃了锁的所有权后返回。使用条件变量的典型编程风格是将锁用于同步某些共享状态的权限,那些对状态的某些特定改变感兴趣的线程,它们重复调用
wait()
方法,直到看到所期望的改变发生;而对于修改状态的线程,它们将当前状态改变为可能是等待者所期待的新状态后,调用notify()
方法或者notify_all()
方法。信号量对象
这是计算机科学史上最古老的同步原语之一,早期的荷兰科学家 Edsger W. Dijkstra 发明了它。(他使用名称
P()
和V()
而不是acquire()
和release()
)。一个信号量管理一个内部计数器,该计数器因
acquire()
方法的调用而递减,因release()
方法的调用而递增。 计数器的值永远不会小于零;当acquire()
方法发现计数器为零时,将会阻塞,直到其它线程调用release()
方法。事件对象
这是线程之间通信的最简单机制之一:一个线程发出事件信号,而其他线程等待该信号。
一个事件对象管理一个内部标志,调用
set()
方法可将其设置为true,调用clear()
方法可将其设置为false,调用wait()
方法将进入阻塞直到标志为true。定时器对象
此类表示一个操作应该在等待一定的时间之后运行 --- 相当于一个定时器。
Timer
类是Thread
类的子类,因此可以像一个自定义线程一样工作。与线程一样,通过调用
start()
方法启动定时器。而cancel()
方法可以停止计时器(在计时结束前), 定时器在执行其操作之前等待的时间间隔可能与用户指定的时间间隔不完全相同。栅栏对象
3.2 新版功能.
栅栏类提供一个简单的同步原语,用于应对固定数量的线程需要彼此相互等待的情况。线程调用
wait()
方法后将阻塞,直到所有线程都调用了wait()
方法。此时所有线程将被同时释放。栅栏对象可以被多次使用,但进程的数量不能改变。
-
-
from threading import Thread,Lock
import random
# 锁的作用
# arr = []
#
# #原始锁处于 "锁定" 或者 "非锁定" 两种状态之一。它被创建时为非锁定状态。它有两个基本方法, acquire() 和 release() 。当状态为非锁定时, acquire() 将状态改为 锁定 并立即返回。当状态是锁定时, acquire() 将阻塞至其他线程调用 release() 将其改为非锁定状态,然后 acquire() 调用重置其为锁定状态并返回。 release() 只在锁定状态下调用; 它将状态改为非锁定并立即返回。如果尝试释放一个非锁定的锁,则会引发 RuntimeError 异常。
#
# l = Lock() # 状态默认是非锁定的
# l.acquire()
#
# def test1():
# l.acquire() # 如果之前的锁是锁定的,再次上锁发生阻塞
# # 如果之前的锁是非锁定的,可以实现上锁
# arr.append(random.randint(1,10))
#
# t = Thread(target=test1)
# t.start()
#
#
#
# def test2():
# arr.append(random.randint(1,0)) """
爬取豆瓣电影top250
"""
# import requests
# import lxml.etree as etree
# urls = ["https://movie.douban.com/top250?start=%s"%i for i in range(0,226,25)]
#
# class Mytest(Thread):
# def __init__(self):
# super(Mytest,self).__init__()
# def run(self):
# while len(urls)>0:
# url = urls.pop()
# res = requests.get(url).text
# html = etree.HTML(res)
# titles = html.xpath("//div[@class='hd']/a/span[1]/text()")
# print(self.name,titles)
#
# for i in range(2):
# mytest = Mytest()
# mytest.start() """
向列表中插入元素并打印列表
"""
# import time
# arr = []
# l = Lock()
# class Mytest(Thread):
# def __init__(self):
# super(Mytest,self).__init__()
# def run(self):
# time.sleep(1)
# l.acquire()
# arr.append(random.randint(0,10))
# print(arr)
# l.release()
#
# for i in range(20):
# t = Mytest()
# t.start() """
递归锁 复用锁 RLock()
在一个线程内可以重复上锁不被阻塞。
"""
from threading import RLock
import time
r = RLock()
l = Lock()
def test1():
r.acquire()
r.acquire()
print("")
time.sleep(2)
r.release()
r.release() def test2():
r.acquire()
print('test2') t = Thread(target=test1)
t.start() t2 = Thread(target=test2)
t2.start() # 死锁
# import time
# l1 = Lock()
# l2 = Lock()
# def fun1():
# l1.acquire()
# print("fun1 is running")
# time.sleep(1)
# l2.acquire() # 阻塞
# print("fun1 is end")
# l1.release()
# l2.acquire()
# def fun2():
# l2.acquire()
# print("fun2 is running")
# l1.acquire() # 阻塞
# print("fun2 is end")
# l2.release()
# l1.release()
#
# t1 = Thread(target=fun1)
# t1.start()
# t2 = Thread(target=fun2)
# t2.start() """
锁的上下文使用方法
向列表中插入元素并打印列表
"""
# import time,random
# arr = []
# l = Lock()
# def fun():
# time.sleep(1)
# with l: # 上锁 自动解锁的功能
# arr.append(random.randint(0,10))
# print(arr)
#
# for i in range(20):
# t = Thread(target=fun)
# t.start() """
条件锁
class Condition(lock=RLock) 默认是递归锁
方法:
acquire() 上锁
release() 释放锁
wait(timeout=) 等待(释放锁) 阻塞(等待被通知)
notify(n=) 通知 唤醒n个线程
wait_for(predicate,timeout=) predicate 是一个函数 返回 True False
notify_all() 唤醒所有线程
"""
# from threading import Condition
# import time
# con = Condition(lock=Lock())
#
# arr = []
#
# class XM(Thread):
# def __init__(self):
# super(XM,self).__init__()
# def run(self):
# with con:
# while True:
# time.sleep(1)
# arr.append(1)
# length = len(arr)
# print("小明添加了1个鱼丸,锅内还有%s个鱼丸"%length)
# if length>=5:
# con.notify_all()
# con.wait()
#
#
# class XH(Thread):
# def __init__(self,name):
# super(XH,self).__init__()
# self.name = name
# def run(self):
# with con:
# while True:
# time.sleep(1)
# arr.pop()
# length = len(arr)
# print("%s吃了1个鱼丸,锅内还有%s个鱼丸"%(self.name,length))
# if length<=0:
# con.notify()
# con.wait()
#
# xm = XM()
# xm.start()
#
# xh = XH("小红1")
# xh.start()
#
# xh1 = XH("小红2")
# xh1.start() """
wait_for(predicate,timeout=)
等待 当predicate 返回值为 False 阻塞 当返回值为True 运行
wait() 等待,阻塞 。直到被 notify
"""
# from threading import Condition
# import time
# con = Condition()
# con.acquire()
#
# def fun():
# time.sleep(5)
# return True
# con.wait_for(fun)
# print(123) """
Semaphore 信号量对象
信号量通常用于保护数量有限的资源,例如数据库服务器。在资源数量固定的任何情况下,都应该使用有界信号量。在生成任何工作线程前,应该在主线程中初始化信号量。
"""
# from threading import Semaphore
# import time
# b = Semaphore(value=3) # 技术面试 每次3个人 # class Ms(Thread):
# def __init__(self):
# super(Ms,self).__init__()
# def run(self):
# with b:
# print("<%s>开始面试,倒计时3秒钟"%self.name)
# time.sleep(3)
# print("<%s>面试结束,有请下一个同学"%self.name)
#
#
# for i in range(20):
# m = Ms()
# m.start() """
事件锁
is_set() 判断事件锁内部开关是否为true
set() 设置事件锁内部开关为 true
clear() 设置事件锁内部开关为 false
wait() 阻塞 等待事件锁内部开关为true 然后运行
"""
# from threading import Event
# import time
#
# e1 = Event()
# e1.set()
#
# e2 = Event()
#
# arr = []
# class XM(Thread):
# def __init__(self):
# super(XM,self).__init__()
# def run(self):
# while True:
# e1.wait()
# time.sleep(1)
# arr.append(1)
# length = len(arr)
# print("小明添加了1个鱼丸,锅内还有%s个鱼丸"%length)
# if length>=5:
# e1.clear()
# e2.set()
#
# class XH(Thread):
# def __init__(self):
# super(XH, self).__init__()
# def run(self):
# while True:
# e2.wait()
# time.sleep(1)
# arr.pop()
# length = len(arr)
# print("小红吃了1个鱼丸,锅内还剩%s个鱼丸"%length)
# if length<=0:
# e2.clear()
# e1.set()
#
# xm = XM()
# xm.start()
# xh = XH()
# xh.start() """
定时器对象
"""
# import time
# def fun():
# time.sleep(3)
# print("123")
#
# fun()
# print("开始") # from threading import Timer
# # Timer 是一个倒计时线程
# def fun():
# print("123")
#
# t = Timer(3,fun)
# t.start()
# print("开始") """
栅栏对象
wait()
"""
# from threading import Barrier,active_count
# import time
#
# b = Barrier(5)
# l = Lock()
#
# class Test(Thread):
# def __init__(self):
# super(Test,self).__init__()
# def run(self):
# b.wait()
# with l:
# print("%s 开始运行"%self.name)
#
# for i in range(20):
# time.sleep(2)
# t = Test()
# with l:
# print("创建了%s线程"%t.name)
# t.start()
-
python中的线程锁的更多相关文章
- 理解 Python 中的线程
原地址:http://blog.jobbole.com/52060/ 本文由 伯乐在线 - acmerfight 翻译自 Akshar Raaj.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 我 ...
- python中的线程技术
#!/user/bin/env python # @Time :2018/7/7 11:42 # @Author :PGIDYSQ #@File :DaemonTest.py import threa ...
- Python中的线程和进程
引入进程和线程的概念及区别 threading模块提供的类: Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, l ...
- python中的各种锁
一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...
- python同步原语--线程锁
多线程锁是python多种同步原语中的其中一种.首先解析一下什么是同步原语,python因为GIL(全局解析锁)的缘故,并没有真正的多线性.另外python的多线程存在一个问题,在多线程编程时,会出现 ...
- python基础24 -----python中的各种锁
一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...
- python网络编程--线程锁(互斥锁Mutex)
一:为什么需要线程锁 一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况? 很简单,假设你有A,B两 ...
- python网络编程--线程(锁,GIL锁,守护线程)
1.线程 1.进程与线程 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率.很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观 ...
- Python GIL、线程锁、信号量及事件
GIL是什么? GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编 ...
随机推荐
- 数据结构学习笔记——顺序数组2
接着昨天的数组操作,数组初始化好了,我们要往里面添加元素,可以在尾部追加或者插入,刚开始数组为空,所以先追加 int AppendList(SqList* pArr, ElemType val) { ...
- VMware Workstation 无法打开内核设备:\\Global\\vmx86
解决方法:win10系统,打开“服务”后右击选择使用管理员打开.然后在一大串服务中找到vm开头的服务项,全部都启动.重新启动vm就ok了(vm需要以管理员身份打开).不用复杂的代码!!
- c# 使用 java的 rsa 进行签名
/// <summary> /// 类名:RSAFromPkcs8 /// 功能:RSA加密.解密.签名.验签 /// 详细:该类对Java生成的密钥进行解密和签名以及验签专用类,不需要修 ...
- java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy
问题:Error creating bean with name 'sqlSessionFactory' defined in class path resource [applicationCont ...
- axios以form-data形式的传递参数遇到的坑
axios默认的Content-type是application/json;charset=UTF-8,如果想要以表单的形式传递参数,只要修改{headers:{'Content-Type':'app ...
- [已解决]报错run `npm audit fix` to fix them, or `npm audit` for details
问题: added 246 packages from 681 contributors and audited 382 packages in 17.509s found 13 vulnerabil ...
- vue-cli中进行微信支付代码详解
最近做微信支付,颇经历一番波折,这里总结一下,便于以后少走弯路: 在进行微信支付,除了需要公众号之外,你还需要一个微信商户.根据商户规则进行商户申请 这是公众号的基本开发配置,这里在微信授权的时候就已 ...
- Unity Shader后处理-搜索灰度效果
如U3D中Hierarchy面板下的搜索效果: 讲解分析: 1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法.顾名思义屏幕后处理就是指在渲染完 ...
- uname - 显示输出系统信息
总览 uname [OPTION]... 描述 显示相应的系统信息. 没有指定选项时,同 -s. -a, --all 显示所有的信息 -m, --machine 显示机器(硬件)类型 -n, --no ...
- log4cplus TimeBasedRollingFileAppender
参考自:http://blog.csdn.net/u010607621/article/details/54944696 对于TimeBasedRollingFileAppender 这个日志appe ...