この記事では、Python マルチスレッドで同期を実現するための 4 つの方法を主に紹介します。編集者が非常に優れていると考えたので、参考として共有します。エディターをフォローして見てみましょう
重要なリソースとは、一度に 1 つのスレッドのみがアクセスできるリソースです。典型的な例はプリンターであり、印刷機能を実行するために一度に 1 つのプログラムのみが使用できます。複数のスレッドが同時に動作できないため、リソースのこの部分にアクセスするコードは通常、クリティカル セクションと呼ばれます。
ロック機構
スレッドのLockクラス。ロックするにはこのクラスのacquire関数を使用し、ロックを解除するにはrealease関数を使用します
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) t.start() t.join()#使线程一个一个执行
スレッドがロックのacquire()メソッドを呼び出してロックを取得するとき、ロックは「ロック」ステータスに入ります。一度に 1 つのスレッドだけがロックを取得できます。この時点で別のスレッドがロックを取得しようとすると、そのスレッドは「ブロック」されます。これは「同期ブロック」と呼ばれます (マルチスレッドの基本概念を参照)。
ロックを所有するスレッドがロックの release() メソッドを呼び出してロックを解放するまで、ロックは「ロック解除」状態になります。スレッド スケジューラは、同期ブロッキング状態にあるスレッドの 1 つを選択してロックを取得し、そのスレッドを実行状態にします。
セマフォ
セマフォは、取得メソッドと解放メソッドも提供します。取得メソッドが呼び出されるたびに、内部カウンタが 0 より大きい場合、1 ずつデクリメントされます。内部カウンタが 0 に等しい場合、スレッドは実行されます。スレッドが内部カウンタ を 1 より大きい位置に更新するために release メソッドを呼び出したことがわかります。
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) value = n.add() print(self.item,value) for item in range(100): t = jdThread(item) t.start() t.join()
変数、つまり特定の条件が満たされた場合にのみスレッドが該当するデータにアクセスできる仕組みです。
""" 一个简单的生产消费者模型,通过条件变量的控制产品数量的增减,调用一次生产者产品就是+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): 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): 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()
import threading import queue import time import random ''' 1.创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。 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
Marco Education Python基礎文法完全解説ビデオ
以上がマルチスレッドを同期する複数の方法を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。