ホームページ  >  記事  >  バックエンド開発  >  Pythonスレッドでの同期ロックの詳しい説明

Pythonスレッドでの同期ロックの詳しい説明

不言
不言オリジナル
2018-04-27 10:01:311509ブラウズ

この記事では、主に Python スレッドの同期ロックに関する情報を詳しく紹介します。興味のある方は参考にしてください。

マルチスレッドを使用するアプリケーションでスレッドの安全性を確保する方法と、スレッド間の同期などの問題について説明します。共有変数へのアクセスは非常に困難な問題であり、マルチスレッドを使用するときに直面する問題でもあります。これは、Python のマルチスレッドを使用してロック Rlock セマフォ条件を使用して同期を確保します。スレッド、後者は共有変数へのアクセスの相互排他を保証します

Lock & RLock: Mutex は、共有変数へのマルチスレッド アクセスを保証するために使用されます
Semaphore オブジェクト: Lock mutex の拡張バージョンであり、複数のスレッドが所有できます。一方、Lock は同時に特定のスレッドのみが所有できます。
イベント オブジェクト: スレッド間の通信方法であり、シグナルに相当します。あるスレッドが別のスレッドにシグナルを送信し、そのスレッドに操作を実行させることができます。
条件オブジェクト: 特定のイベントがトリガーされるか、特定の条件が満たされた場合にのみデータを処理できます

1. ロック (ミューテックス ロック)

ロックの要求 - ロック プールに入って待機 - ロックの取得 - ロック - ロックの解放

Lock (コマンドロック) は、利用可能な最も低いレベルの同期コマンドです。 Lock がロック状態にある場合、Lock は特定のスレッドによって所有されていません。 Lock には、ロックと非ロックの 2 つの状態と 2 つの基本メソッドが含まれています。

Lock はロック プールを持つものと考えることができます。スレッドがロックを要求すると、スレッドはロックを取得した後にプールから解放されるまでプールに置かれます。状態図では、プール内のスレッドは同期ブロッキング状態にあります。

構築メソッド:
Lock()

インスタンスメソッド:
acquire([timeout]): スレッドを同期ブロッキング状態にし、ロックの取得を試みます。
release(): ロックを解放します。スレッドは使用前にロックを取得する必要があります。取得しないと例外がスローされます。

if mutex.acquire():
 counter += 1
 print "I am %s, set counter:%s" % (self.name, counter)
  mutex.release()

2. RLock (リエントラントロック)

RLock (リエントラントロック) は、同じスレッドによって複数回要求できる同期命令です。 RLock は、「所有スレッド」と「再帰レベル」の概念を使用します。ロック状態では、RLock はスレッドによって所有されます。 RLock を所有するスレッドは、acquire() を再度呼び出すことができ、ロックを解放するには、同じ回数 release() を呼び出す必要があります。

RLock には、ロック プールと初期値 0 のカウンターが含まれていると考えることができます。acquire()/release() が正常に呼び出されるたびに、カウンターは +1/-1 になり、0 の場合はカウンターが増加します。 、ロックは解除された状態です。

構築メソッド:
RLock()

インスタンスメソッド:
acquire([timeout])/release(): Lockと同様。

3. セマフォ (共有オブジェクト アクセス)

セマフォについてもう一度話しましょう。正直に言うと、セマフォは私が以前に同様の実装を行うために使用した最新の同期ロックです。すべて、Rlock ではロックとロック解除をペアで行う必要があります。 。 。

セマフォは組み込みカウンターを管理します。
acquire() が呼び出されるたびに組み込みカウンターは -1 になります。
release() が呼び出される場合は組み込みカウンターは +1 になります。カウンタが 0 の場合、acquire() は、他のスレッドが release() を呼び出すまでスレッドをブロックします。

コードに直接アクセスして、セマフォを 3 に制御します。つまり、3 つのスレッドがこのロックを同時に使用でき、残りのスレッドはブロックして待機することしかできません...

#coding:utf-8
#blog xiaorui.cc
import time
import threading

semaphore = threading.Semaphore(3)

def func():
 if semaphore.acquire():
  for i in range(3):
   time.sleep(1)
   print (threading.currentThread().getName() + '获取锁')
  semaphore.release()
  print (threading.currentThread().getName() + ' 释放锁')


for i in range(5):
 t1 = threading.Thread(target=func)
 t1.start()

4. イベント (スレッド間通信)

イベントには内部的にフラグが含まれており、最初は false です。

set() を使用して true に設定することも、clear() を使用して false にリセットすることもできます


もう 1 つの最も重要な関数は wait です。 (timeout=None)、イベントの内部フラグ ビットが true に設定されるかタイムアウトになるまで、現在のスレッドをブロックするために使用されます。内部フラグが true の場合、wait() 関数はそれを理解して戻ります。

import threading
import time

class MyThread(threading.Thread):
 def __init__(self, signal):
  threading.Thread.__init__(self)
  self.singal = signal

 def run(self):
  print "I am %s,I will sleep ..."%self.name
  self.singal.wait()
  print "I am %s, I awake..." %self.name

if __name__ == "__main__":
 singal = threading.Event()
 for t in range(0, 3):
  thread = MyThread(singal)
  thread.start()

 print "main thread sleep 3 seconds... "
 time.sleep(3)

 singal.set()

5. 条件 (スレッド同期)

条件は、Lock や RLock よりも高度な機能を提供し、複雑なスレッド同期の問題を制御できます。 threadiong.Condition は内部的に threadion オブジェクト (デフォルトは RLock) を維持します。これは、Condigtion オブジェクトの作成時にパラメータとして渡すことができます。 Condition には、acquire メソッドと release メソッドも用意されており、その意味はホストのacquire メソッドと release メソッドと同じです。実際には、単に内部ホスト オブジェクトの対応するメソッドを呼び出すだけです。 Condition は次のメソッドも提供します (特に注意: これらのメソッドは取得後にのみ呼び出すことができ、そうでない場合は RuntimeError 例外が報告されます):

Condition.wait([timeout]):


wait メソッドはリリースします。内部占有スレッドであり、スレッドは通知の受信後に起動されるか、タイムアウトになるまで中断されます (タイムアウト パラメーターが指定されている場合)。スレッドが目覚めてスレッドを再び占有すると、プログラムは実行を継続します。

Condition.notify():

一時停止されたスレッドを起動します (一時停止されたスレッドがある場合)。注:notify() メソッドは、占有されているメモリを解放しません。

Condition.notify_all()
Condition.notifyAll()

唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

对于Condition有个例子,大家可以观摩下。

from threading import Thread, Condition
import time
import random

queue = []
MAX_NUM = 10
condition = Condition()

class ProducerThread(Thread):
 def run(self):
  nums = range(5)
  global queue
  while True:
   condition.acquire()
   if len(queue) == MAX_NUM:
    print "Queue full, producer is waiting"
    condition.wait()
    print "Space in queue, Consumer notified the producer"
   num = random.choice(nums)
   queue.append(num)
   print "Produced", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


class ConsumerThread(Thread):
 def run(self):
  global queue
  while True:
   condition.acquire()
   if not queue:
    print "Nothing in queue, consumer is waiting"
    condition.wait()
    print "Producer added something to queue and notified the consumer"
   num = queue.pop(0)
   print "Consumed", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


ProducerThread().start()
ConsumerThread().start()

相关推荐:

python多线程之事件Event的使用详解

python线程池threadpool的实现

以上がPythonスレッドでの同期ロックの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。