>백엔드 개발 >파이썬 튜토리얼 >Python 스레드의 동기화 잠금에 대한 자세한 설명

Python 스레드의 동기화 잠금에 대한 자세한 설명

不言
不言원래의
2018-04-27 10:01:311552검색

이 글은 주로 Python 스레드의 동기화 잠금 관련 정보를 자세히 소개합니다. 관심 있는 친구가 참고할 수 있습니다.

멀티 스레드를 사용하는 응용 프로그램에서 스레드 안전성을 보장하는 방법 및 스레드 간 동기화와 같은 문제 또는 공유 변수에 대한 액세스는 매우 어려운 문제이며 멀티 스레딩을 사용할 때 직면하는 문제이기도 합니다. 제대로 처리하지 않으면 심각한 결과를 초래할 수 있습니다. Python 멀티 스레딩을 사용하여 잠금 Rlock 세마포 이벤트 조건을 사용하여 간의 동기화를 보장합니다. 후자는 공유 변수에 대한 액세스의 상호 배제를 보장합니다

Lock & RLock: Mutex는 공유 변수에 대한 다중 스레드 액세스를 보장하는 데 사용됩니다.
Semaphore 객체: Lock mutex의 향상된 버전으로, 여러 스레드가 소유할 수 있습니다. 반면 Lock은 동시에 특정 스레드에서만 소유할 수 있습니다.
이벤트 객체: 스레드 간 통신 방법으로, 신호와 동일합니다. 하나의 스레드가 다른 스레드에 신호를 보낸 다음 작업을 수행하도록 할 수 있습니다.
조건 객체: 특정 이벤트가 발생하거나 특정 조건이 충족된 후에만 데이터를 처리할 수 있습니다.

1. 잠금(뮤텍스 잠금)

잠금 요청 - 잠금 풀에 들어가서 대기 - 잠금 획득 - 잠김 - 잠금 해제

Lock(명령 잠금)은 사용 가능한 가장 낮은 수준의 동기화 명령입니다. Lock이 잠긴 상태이면 특정 스레드가 소유하지 않습니다. 잠금에는 잠긴 상태와 잠기지 않은 상태라는 두 가지 상태와 두 가지 기본 방법이 있습니다.

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. Semaphore(공유 객체 액세스)

Semaphore에 대해 다시 이야기해 보겠습니다. 솔직히 말해서 Semaphore는 제가 이전에 비슷한 구현을 구현하기 위해 사용한 최신 동기화 잠금입니다. Rlock에는 쌍으로 잠금 및 잠금 해제가 필요합니다. . .

세마포어는 내장 카운터를 관리합니다.
acquire()가 호출될 때마다 내장 카운터 -1
release()가 호출되면 카운터는 0보다 작을 수 없습니다. 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. 이벤트(스레드 간 통신)

이벤트에는 내부적으로 거짓인 플래그가 포함되어 있습니다.

set()를 사용하여 true로 설정하거나
clear()를 사용하여 false로 재설정할 수 있습니다.
is_set()을 사용하여 플래그 비트의 상태를 확인할 수 있습니다.

또 다른 가장 중요한 기능은 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은 내부적으로 스레드 개체(기본값은 RLock)를 유지 관리하며, 이는 Condigtion 개체를 생성할 때 매개 변수로 전달될 수 있습니다. Condition은 또한 호스트의 획득 및 해제 메서드와 의미가 일치하는 획득 및 해제 메서드를 제공합니다. 실제로 이는 내부 호스트 개체의 해당 메서드를 호출하기만 하면 됩니다. Condition은 또한 다음 메소드를 제공합니다(특히 참고: 이 메소드는 획득한 후에만 호출할 수 있습니다. 그렇지 않으면 RuntimeError 예외가 보고됩니다):

Condition.wait([timeout]):

wait 메소드가 출시됩니다. 내부 점유 스레드 및 스레드는 알림을 받거나 시간 초과(timeout 매개변수가 제공되는 경우)를 받은 후 깨어날 때까지 일시 중단됩니다. 스레드가 활성화되어 스레드를 다시 점유하면 프로그램은 계속 실행됩니다.

Condition.notify():

정지된 스레드를 깨웁니다(정지된 스레드가 있는 경우). 참고: inform() 메소드는 점유된 메모리를 해제하지 않습니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.