マルチスレッドを同期する複数の方法を共有する

Y2J
リリース: 2017-05-11 11:13:01
オリジナル
1388 人が閲覧しました

この記事では、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()
ログイン後にコピー

条件判断

いわゆる条件

変数、つまり特定の条件が満たされた場合にのみスレッドが該当するデータにアクセスできる仕組みです。

Conditionクラスを使用して完了します。ロック機構のようにも使用できるため、取得メソッドと解放メソッドもあり、待機メソッド、通知メソッド、および通知すべてのメソッドもあります。

"""
一个简单的生产消费者模型,通过条件变量的控制产品数量的增减,调用一次生产者产品就是+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()
ログイン後にコピー

同期Queue

putメソッドとtask_doneメソッド、キューには未完了のタスクnumがあり、シーケンスnum+1に配置され、タスクはシーケンスnum-1に配置されます。

import threading
import queue
import time
import random

&#39;&#39;&#39;
1.创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。
2.将经过填充数据的实例传递给线程类,后者是通过继承 threading.Thread 的方式创建的。
3.每次从队列中取出一个项目,并使用该线程中的数据和 run 方法以执行相应的工作。
4.在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号。
5.对队列执行 join 操作,实际上意味着等到队列为空,再退出主程序。
&#39;&#39;&#39;

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)
&#39;&#39;&#39;
初始化函数接受一个数字来作为该队列的容量,如果传递的是
一个小于等于0的数,那么默认会认为该队列的容量是无限的.
&#39;&#39;&#39;
for i in range(2):
  jdThread(i,q).start()#两个线程同时完成任务

for i in range(10):
  q.put(i)#put方法使得未完成的任务数量+1
ログイン後にコピー
【関連おすすめ】

1.

Python無料ビデオチュートリアル

3.

Marco Education Python基礎文法完全解説ビデオ

以上がマルチスレッドを同期する複数の方法を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート