当前位置: 主页 > Python语言

python 多线程并发锁-python线程锁

发布时间:2023-02-09 11:22   浏览次数:次   作者:佚名

文章目录

一、简介

关键资源是一次只能由一个线程访问的资源。 一个典型的例子是打印机,它一次只能被一个程序使用来执行打印功能,因为多个线程不能同时操作,而访问这部分资源的代码通常是针对临界区调用的。

2.锁定机制

threading的Lock类用该类的acquire函数加锁,用release函数解锁。

import threading
import time
 
class Num:
    def __init__(self):
        self.num = 0
        self.lock = threading.Lock()
    def add(self):
        self.lock.acquire()#加锁,锁住相应的资源
        self.num += 1
        num = self.num
        self.lock.release()#解锁,离开该资源
        return num
 
n = Num()
class jdThread(threading.Thread):
    def __init__(self,item):
        threading.Thread.__init__(self)
        self.item = item
    def run(self):
        time.sleep(2)
        value = n.add()#将num加1,并输出原来的数据和+1之后的数据
        print(self.item,value)
 
for item in range(5):
    t = jdThread(item)

线程池实现多线程并发_python线程锁_python 多线程并发锁

t.start() t.join()#使线程一个一个执行

当线程调用锁的acquire()方法获取锁时,锁进入“已锁定”状态。 一次只有一个线程可以获取锁。 如果此时另一个线程试图获取锁,则该线程将变为“阻塞”状态python 多线程并发锁,称为“同步阻塞”(参见多线程基本概念)。

直到拥有锁的线程调用锁的release()方法释放锁,锁才进入“解锁”状态。 线程调度器选择其中一个处于同步阻塞状态的线程获取锁,并使该线程进入运行状态。

3.信号量

信号量还提供了acquire方法和release方法。 每当调用acquire方法时python 多线程并发锁,如果内部计数器大于0,就会减1。如果内部计数器等于0,线程就会被阻塞,直到有线程调用release方法。 内部计数器更新到大于 1 的位置。

import threading
import time
class Num:
    def __init__(self):
        self.num = 0
        self.sem = threading.Semaphore(value = 3)
        #允许最多三个线程同时访问资源
 
    def add(self):
        self.sem.acquire()#内部计数器减1
        self.num += 1
        num = self.num
        self.sem.release()#内部计数器加1
        return num
     
n = Num()
class jdThread(threading.Thread):
    def __init__(self,item):
        threading.Thread.__init__(self)
        self.item = item
    def run(self):
        time.sleep(2)

python 多线程并发锁_线程池实现多线程并发_python线程锁

value = n.add() print(self.item,value) for item in range(100): t = jdThread(item) t.start() t.join()

4.条件判断

所谓条件变量,即这种机制是一个线程只有在满足一定的条件后,才能访问相关的数据。

它使用Condition 类来完成。 由于它也可以像锁机制一样使用,所以它也有acquire方法和release方法,它还有wait、notify和notifyAll方法。

"""
一个简单的生产消费者模型,通过条件变量的控制产品数量的增减,调用一次生产者产品就是+1,调用一次消费者产品就会-1.
"""
 
"""
使用 Condition 类来完成,由于它也可以像锁机制那样用,所以它也有 acquire 方法和 release 方法,而且它还有
wait, notify, notifyAll 方法。
"""
 
import threading
import queue,time,random
 
class Goods:#产品类
    def __init__(self):
        self.count = 0
    def add(self,num = 1):
        self.count += num
    def sub(self):

python线程锁_线程池实现多线程并发_python 多线程并发锁

if self.count>=0: self.count -= 1 def empty(self): return self.count <= 0 class Producer(threading.Thread):#生产者类 def __init__(self,condition,goods,sleeptime = 1):#sleeptime=1 threading.Thread.__init__(self) self.cond = condition self.goods = goods self.sleeptime = sleeptime def run(self): cond = self.cond goods = self.goods while True: cond.acquire()#锁住资源 goods.add() print("产品数量:",goods.count,"生产者线程") cond.notifyAll()#唤醒所有等待的线程--》其实就是唤醒消费者进程 cond.release()#解锁资源 time.sleep(self.sleeptime) class Consumer(threading.Thread):#消费者类 def __init__(self,condition,goods,sleeptime = 2):#sleeptime=2 threading.Thread.__init__(self) self.cond = condition self.goods = goods self.sleeptime = sleeptime def run(self):

python线程锁_线程池实现多线程并发_python 多线程并发锁

cond = self.cond goods = self.goods while True: time.sleep(self.sleeptime) cond.acquire()#锁住资源 while goods.empty():#如无产品则让线程等待 cond.wait() goods.sub() print("产品数量:",goods.count,"消费者线程") cond.release()#解锁资源 g = Goods() c = threading.Condition() pro = Producer(c,g) pro.start() con = Consumer(c,g) con.start()

五、同步队列

put方法和task_done方法,queue中有未完成任务num个,依次put num+1个,task依次num-1个。 当所有任务完成时,任务结束。

import threading
import queue
import time
import random
 
'''
1.创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。

python 多线程并发锁_线程池实现多线程并发_python线程锁

2.将经过填充数据的实例传递给线程类,后者是通过继承 threading.Thread 的方式创建的。 3.每次从队列中取出一个项目,并使用该线程中的数据和 run 方法以执行相应的工作。 4.在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号。 5.对队列执行 join 操作,实际上意味着等到队列为空,再退出主程序。 '''
class jdThread(threading.Thread): def __init__(self,index,queue): threading.Thread.__init__(self) self.index = index self.queue = queue def run(self): while True: time.sleep(1) item = self.queue.get() if item is None: break print("序号:",self.index,"任务",item,"完成") self.queue.task_done()#task_done方法使得未完成的任务数量-1 q = queue.Queue(0) ''' 初始化函数接受一个数字来作为该队列的容量,如果传递的是 一个小于等于0的数,那么默认会认为该队列的容量是无限的. ''' for i in range(2): jdThread(i,q).start()#两个线程同时完成任务 for i in range(10): q.put(i)#put方法使得未完成的任务数量+1