>  기사  >  백엔드 개발  >  멀티 스레드를 동기화하는 다양한 방법 공유

멀티 스레드를 동기화하는 다양한 방법 공유

Y2J
Y2J원래의
2017-05-11 11:13:011393검색

이 기사에서는 동기화를 달성하기 위한 Python 멀티스레딩의 네 가지 방법을 주로 소개합니다. 편집자는 이것이 꽤 좋다고 생각하므로 지금 공유하고 참고용으로 제공하겠습니다. 편집기를 따라가서 살펴보겠습니다.

한 번에 하나의 스레드에서만 액세스할 수 있는 리소스가 대표적인 예입니다. 프린터는 한 번에 하나의 프로그램에서만 사용할 수 있습니다. 한 번에 두 개 이상의 스레드에서 사용할 수 없기 때문에 인쇄 기능을 수행하는 데 사용됩니다. 스레드는 동시에 작동하며 리소스의 이 부분에 액세스하는 코드를 일반적으로 임계 섹션이라고 합니다.

잠금 메커니즘

Threading의 Lock 클래스, 이 클래스의 획득함수를 사용하여 잠그고 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() 메서드를 호출하면 잠금은 "잠긴" 상태로 들어갑니다. 한 번에 하나의 스레드만 잠금을 얻을 수 있습니다. 이때 다른 스레드가 잠금을 얻으려고 시도하면 해당 스레드는 "차단"되며, 이를 "동기 차단"이라고 합니다(멀티스레딩의 기본 개념 참조).

잠금을 소유한 스레드가 잠금의 release() 메서드를 호출하여 잠금을 해제할 때까지 잠금은 "잠금 해제" 상태로 들어갑니다. 스레드 스케줄러는 동기 차단 상태의 스레드 중 하나를 선택하여 잠금을 획득하고 해당 스레드를 실행 상태로 진입시킵니다.

세마포어

세마포어는 획득 메서드와 해제 메서드도 제공합니다. 획득 메서드가 호출될 때마다 내부 카운터가 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)
    value = n.add()
    print(self.item,value)

for item in range(100):
  t = jdThread(item)
  t.start()
  t.join()

조건부 판단소위 조건부

변수

, 즉 이 메커니즘은 특정 조건 후에 충족되면 스레드만 관련 데이터에 액세스할 수 있습니다.
완료를 위해 Condition 클래스를 사용합니다. 잠금 메커니즘처럼 사용할 수도 있으므로 획득 및 해제 메서드도 있고 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):
    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()

동기화

put 메소드 및 task_done 메소드, 큐에는 완료되지 않은 작업 수 num, 시퀀스 num+1, task 포함 순서대로 num-1. 모든 작업이 완료되면 작업이 종료됩니다.

아아아아

[관련 추천]

1.

Python 무료 동영상 튜토리얼

Python 학습 매뉴얼

3.

마르코 에듀케이션의 파이썬 기초 문법 전체 설명 영상

위 내용은 멀티 스레드를 동기화하는 다양한 방법 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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