Partagez plusieurs méthodes de synchronisation multi-threads

Y2J
Libérer: 2017-05-11 11:13:01
original
1374 Les gens l'ont consulté

Cet article présente principalement les quatre méthodes de multi-threading Python pour réaliser la synchronisation. L'éditeur pense que c'est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil

Les ressources critiques sont les ressources qui ne peuvent être accessibles que par un seul thread à la fois. Un exemple typique est l'imprimante, qui ne peut être utilisée que par un programme à la fois. effectuer la fonction d'impression, car elle ne peut pas être utilisée par plus d'un thread à la fois, et le code qui accède à cette partie de la ressource est généralement appelé section critique.

Mécanisme de verrouillage

Classe Lock de Threading, utilisez la fonction acquérir de cette classe pour verrouiller et utilisez la fonction de libération pour déverrouiller

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()#使线程一个一个执行
Copier après la connexion

Lorsqu'un thread appelle la méthode acquire() du verrou pour acquérir le verrou, le verrou entre dans l'état "verrouillé" . Un seul thread à la fois peut obtenir le verrou. Si un autre thread tente d'obtenir le verrou à ce moment-là, le thread deviendra "bloqué", ce qu'on appelle "blocage synchrone" (voir le concept de base du multi-threading).

Jusqu'à ce que le thread propriétaire du verrou appelle la méthode release() du verrou pour libérer le verrou, le verrou entre dans l'état "déverrouillé". Le planificateur de threads sélectionne l'un des threads dans l'état de blocage synchrone pour obtenir le verrou et fait passer le thread à l'état d'exécution.

Semaphore

Semaphore fournit également la méthode d'acquisition et la méthode de libération Chaque fois que la méthode d'acquisition est appelée, si le compteur interne est supérieur à 0, il est décrémenté de 1. Si le compteur interne est égal à 0, le thread sera bloqué jusqu'à ce qu'un thread appelle la méthode release pour mettre à jour le compteur interne

à une position supérieure à 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()
Copier après la connexion

Jugement conditionnelLa

variable

conditionnelle dite signifie que ce mécanisme est basé sur certaines conditions étant satisfait Ce n'est qu'alors que le thread peut accéder aux données pertinentes.
Il utilise la classe Condition pour terminer. Puisqu'il peut également être utilisé comme un mécanisme de verrouillage, il possède également des méthodes d'acquisition et de libération, ainsi que des méthodes wait, notify et 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()
Copier après la connexion
Synchronisation

File d'attenteMéthode put et méthode task_done, la file d'attente a un certain nombre de tâches inachevées num, mises à tour de rôle num+1 , Les tâches sont séquentiellement numéro-1. La tâche se termine lorsque toutes les tâches sont terminées.

[Recommandations associées]
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
Copier après la connexion

1

Tutoriel vidéo gratuit Python

2.

Manuel d'apprentissage Python

3. Vidéo de Marco Education expliquant les bases de la grammaire Python

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!