锁对象

原始锁是一个在锁定时不属于特定线程的同步基元组件。在Python中,它是能用的最低级的同步基元组件,由 _thread 扩展模块直接实现。

原始锁处于 "锁定" 或者 "非锁定" 两种状态之一。它被创建时为非锁定状态。它有两个基本方法, acquire() 和 release() 。当状态为非锁定时, acquire() 将状态改为 锁定 并立即返回。当状态是锁定时, acquire() 将阻塞至其他线程调用 release() 将其改为非锁定状态,然后 acquire() 调用重置其为锁定状态并返回。 release() 只在锁定状态下调用; 它将状态改为非锁定并立即返回。如果尝试释放一个非锁定的锁,则会引发 RuntimeError  异常。

锁同样支持 上下文管理协议。

当多个线程在 acquire() 等待状态转变为未锁定被阻塞,然后 release() 重置状态为未锁定时,只有一个线程能继续执行;至于哪个等待线程继续执行没有定义,并且会根据实现而不同。

acquire(blocking=Truetimeout=-1)可以阻塞或非阻塞地获得锁。当调用时参数 blocking 设置为 True (缺省值),阻塞直到锁被释放,然后将锁锁定并返回 True 。在参数 blocking 被设置为 False 的情况下调用,将不会发生阻塞。如果调用时 blocking 设为 True 会阻塞,并立即返回 False ;否则,将锁锁定并返回 True。当浮点型 timeout 参数被设置为正值调用时,只要无法获得锁,将最多阻塞 timeout 设定的秒数。timeout 参数被设置为 -1 时将无限等待。当 blocking 为 false 时,timeout 指定的值将被忽略。如果成功获得锁,则返回 True,否则返回 False (例如发生 超时 的时候)。

在 3.2 版更改: 新的 timeout 形参。
在 3.2 版更改: 现在如果底层线程实现支持,则可以通过POSIX上的信号中断锁的获取。

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. The notify_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中的线程锁的更多相关文章

  1. 理解 Python 中的线程

    原地址:http://blog.jobbole.com/52060/ 本文由 伯乐在线 - acmerfight 翻译自 Akshar Raaj.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 我 ...

  2. python中的线程技术

    #!/user/bin/env python # @Time :2018/7/7 11:42 # @Author :PGIDYSQ #@File :DaemonTest.py import threa ...

  3. Python中的线程和进程

    引入进程和线程的概念及区别 threading模块提供的类:   Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, l ...

  4. python中的各种锁

    一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...

  5. python同步原语--线程锁

    多线程锁是python多种同步原语中的其中一种.首先解析一下什么是同步原语,python因为GIL(全局解析锁)的缘故,并没有真正的多线性.另外python的多线程存在一个问题,在多线程编程时,会出现 ...

  6. python基础24 -----python中的各种锁

    一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...

  7. python网络编程--线程锁(互斥锁Mutex)

    一:为什么需要线程锁 一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况? 很简单,假设你有A,B两 ...

  8. python网络编程--线程(锁,GIL锁,守护线程)

    1.线程 1.进程与线程 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率.很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观 ...

  9. Python GIL、线程锁、信号量及事件

    GIL是什么? GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编 ...

随机推荐

  1. Idea 导入项目不能运行

    1.项目结构里面配置sdk,配置output输出目录 2.配置语言等级 配置src源文件目录 配置目录里面添加application,添加main class

  2. Access数据库中自动编号字段重置为1

    在清空一张ACESS数据库表后,在重添加数据之前,希望此表的自动编号能从1开始,怎么办呢? 下面的方法告诉我们,除了通过转存数据库表的方法外,还有几种更简单的方法: 方法一(前提:数据库表可带内容进行 ...

  3. 面向对象(三)——组合、多态、封装、property装饰器

    组合.多态.封装.property装饰器 一.组合 1.什么是组合 组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象 class Foo(): pass class Bar(): pas ...

  4. win7+ubuntu双系统安装

    XP+ubuntu双系统可參考 xp硬盘上安装ubuntu12.04双系统 1.XP安全不再,最终将吾等磨机的人逼上梁山,是时候做一个win7+ubuntu的双系统了. 废话少说,直接进入主题,先腾出 ...

  5. idea springboot 打包 war

    1.pom文件中将项目改为   war

  6. 关于HTML 5 canvas 的基础教程

    HTML 5 规范引进了很多新特性,其中最令人期待的之一就是 canvas 元素.HTML 5 canvas 提供了通过 JavaScript 绘制图形的方法,此方法使用简单但功能强大.每一个canv ...

  7. Arrays 001

    1.1 Array Initalization First of all, we need know Java arrays is static. When the array is initiali ...

  8. 链表list

    Don't  lost link! list与vector不同之处在于元素的物理地址可以任意. 为保证对列表元素访问的可行性,逻辑上互为前驱和后继的元素之间,应维护某种索引关系.这种索引关系,可抽象地 ...

  9. CentOS 7 編譯qBittorrent Web UI安裝指南

    前言 以下是安装qBittorrent教学. 适用于CentOS7或更新版本 适用于qBittorrent4.1.5或更新版本 安裝須知 qBittorrent基于libtorrent,所以必须先安装 ...

  10. 欧拉定理、欧拉函数、a/b%c

    怕忘了…… 欧拉函数 定义.证明.打表方法 欧拉定理 定义.证明 https://blog.csdn.net/zzkksunboy/article/details/73061013 剩余系.完系.简系 ...