python中的线程锁

锁对象html

原始锁是一个在锁定时不属于特定线程的同步基元组件。在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 (例如发生 超时 的时候)。app

在 3.2 版更改: 新的 timeout 形参。
在 3.2 版更改: 如今若是底层线程实现支持,则能够经过POSIX上的信号中断锁的获取。

release()dom

释放一个锁。这个方法能够在任何线程中调用,不单指得到锁的线程。当锁被锁定,将它重置为未锁定,并返回。若是其余线程正在等待这个锁解锁而被阻塞,只容许其中一个容许。在未锁定的锁调用时,会引起  RuntimeError 异常。没有返回值。

递归锁对象

重入锁是一个能够被同一个线程屡次获取的同步基元组件。在内部,它在基元锁的锁定/非锁定状态上附加了 "所属线程" 和 "递归等级" 的概念。在锁定状态下,某些线程拥有锁 ; 在非锁定状态下, 没有线程拥有它。ide

若要锁定锁,线程调用其 acquire() 方法;一旦线程拥有了锁,方法将返回。若要解锁,线程调用 release() 方法。 acquire()/release() 对能够嵌套;只有最终 release() (最外面一对的 release() ) 将锁解开,才能让其余线程继续处理 acquire() 阻塞。函数

递归锁也支持 上下文管理协议。ui

条件对象

条件变量老是与某种类型的锁对象相关联,锁对象能够经过传入得到,或者在缺省的状况下自动建立。当多个条件变量须要共享同一个锁时,传入一个锁颇有用。锁是条件对象的一部分,你没必要单独地跟踪它。

条件变量服从 上下文管理协议:使用 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("123")
    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()
View Code
相关文章
相关标签/搜索