Python互斥锁(Lock)-解决多线程安全问题,python线程锁的用法

  Python互斥锁(Lock):解决多线程安全问题,python线程锁的用法

  本文主要介绍如何使用多线程锁lock=threading。python中的Lock(),有很好的参考价值。希望对大家有帮助。如有错误或不足之处,请不吝赐教。

  00-1010多线程锁=线程。Lock()使用查询解决方案的例子python多线程锁的概念锁可以从概念线程不安全线程锁中独立提取。

  

目录

  

多线程锁lock=threading.Lock()使用

  多线程同时执行。如果我们需要先执行线程A,再执行线程B,该怎么办?

  

疑问

  使用python的多线程锁。

  

解决方法

  无多线程锁定:

  def a():

  对于范围(3):中的I

  打印( a%d % (i 1))

  时间.睡眠(1)

  定义b():

  对于范围(3):中的I

  打印( b%d % (i 1))

  时间.睡眠(1)

  T=螺纹。线程(目标=a)

  启动()

  T=螺纹。线程(目标=b)

  启动()

  Run:如你所见,线程A和B是同时执行的。

  第一等的

  b1

  a2b2

  a3

  b3

  进程结束,退出代码为0

  带多线程锁的锁:

  锁=线程。锁定()

  def a():

  lock.acquire()

  对于范围(3):中的I

  打印( a%d % (i 1))

  时间.睡眠(1)

  lock.release()

  定义b():

  lock.acquire()

  对于范围(3):中的I

  打印( b%d % (i 1))

  时间.睡眠(1)

  lock.release()

  T=螺纹。线程(目标=a)

  启动()

  T=螺纹。线程(目标=b)

  启动()

  运行结果:可以看到,先执行完线程A,再执行线程B。

  第一等的

  主动脉第二声

  a3

  b1

  b2

  b3

  进程结束,退出代码为0

  

例子

  

python多线程中锁的概念

  互斥=线程。锁定()

  #锁的使用

  #创建一个锁

  互斥=线程。锁定()

  #锁定

  mutex . acquire([超时])

  #发布

  mutex.release()

  

锁可以独立提取出来

  有几个人问我锁定一个资源是什么感觉。其实不是锁定一个资源,而是锁定。您可以定义多个锁,如下面的代码所示。当您需要独占一个资源时,任何锁都可以锁定该资源。

  就像你可以用不同的锁锁住同一扇门一样。

  导入线程

  导入时间

  计数器=0

  Counter_lock=线程。Lock() #只定义一个锁,而不是资源上的锁。您可以定义多个锁,如下两行代码所示。当你需要占用这个资源的时候,任何锁都可以锁定这个资源。

  counter_lock2=线程。英语字母表中第十二个字母

  ock()

  counter_lock3 = threading.Lock()

  #可以使用上边三个锁的任何一个来锁定资源

  class MyThread(threading.Thread):#使用类定义thread,继承threading.Thread

   def __init__(self,name):

   threading.Thread.__init__(self)

   self.name = "Thread-" + str(name)

   def run(self): #run函数必须实现

   global counter,counter_lock #多线程是共享资源的,使用全局变量

   time.sleep(1);

   if counter_lock.acquire(): #当需要独占counter资源时,必须先锁定,这个锁可以是任意的一个锁,可以使用上边定义的3个锁中的任意一个

   counter += 1

   print "I am %s, set counter:%s" % (self.name,counter)

   counter_lock.release() #使用完counter资源必须要将这个锁打开,让其他线程使用

  if __name__ == "__main__":

   for i in xrange(1,101):

   my_thread = MyThread(i)

   my_thread.start()

  

  

线程不安全

  最普通的一个多线程小例子。我一笔带过地讲一讲,我创建了一个继承Thread类的子类MyThread,作为我们的线程启动类。按照规定,重写Thread的run方法,我们的线程启动起来后会自动调用该方法。于是我首先创建了10个线程,并将其加入列表中。再使用一个for循环,开启每个线程。在使用一个for循环,调用join方法等待所有线程结束才退出主线程。

  这段代码看似简单,但实际上隐藏着一个很大的问题,只是在这里没有体现出来。你真的以为我创建了10个线程,并按顺序调用了这10个线程,每个线程为n增加了1.实际上,有可能是A线程执行了n++,再C线程执行了n++,再B线程执行n++。

  这里涉及到一个锁的问题,如果有多个线程同时操作一个对象,如果没有很好地保护该对象,会造成程序结果的不可预期(比如我们在每个线程的run方法中加入一个time.sleep(1),并同时输出线程名称,则我们会发现,输出会乱七八糟。因为可能我们的一个print语句只打印出一半的字符,这个线程就被暂停,执行另一个去了,所以我们看到的结果很乱),这种现象叫做线程不安全

  

  

线程锁

  于是,Threading模块为我们提供了一个类,Threading.Lock,锁。我们创建一个该类对象,在线程函数执行前,抢占该锁,执行完成后,释放该锁,则我们确保了每次只有一个线程占有该锁。这时候对一个公共的对象进行操作,则不会发生线程不安全的现象了。

  于是,我们把代码更改如下:

  

# coding : uft-8

  __author__ = Phtih0n

  import threading, time

  class MyThread(threading.Thread):

      def __init__(self):

          threading.Thread.__init__(self)

      def run(self):

          global n, lock

          time.sleep(1)

          if lock.acquire():

              print n , self.name

              n += 1

              lock.release()

  if "__main__" == __name__:

      n = 1

      ThreadList = []

      lock = threading.Lock()

      for i in range(1, 200):

          t = MyThread()

          ThreadList.append(t)

      for t in ThreadList:

          t.start()

      for t in ThreadList:

          t.join()

  

1 Thread-2
2 Thread-3
3 Thread-4
4 Thread-6
5 Thread-7
6 Thread-1
7 Thread-8
8 Thread-9
9 Thread-5

Process finished with exit code 0

  

  我们看到,我们先建立了一个threading.Lock类对象lock,在run方法里,我们使用lock.acquire()获得了这个锁。此时,其他的线程就无法再获得该锁了,他们就会阻塞在if lock.acquire()这里,直到锁被另一个线程释放:lock.release()。

  所以,if语句中的内容就是一块完整的代码,不会再存在执行了一半就暂停去执行别的线程的情况。所以最后结果是整齐的。

  就如同在java中,我们使用synchronized关键字修饰一个方法,目的一样,让某段代码被一个线程执行时,不会打断跳到另一个线程中。

  这是多线程占用一个公共对象时候的情况。如果多个线程要调用多个现象,而A线程调用A锁占用了A对象,B线程调用了B锁占用了B对象,A线程不能调用B对象,B线程不能调用A对象,于是一直等待。这就造成了线程死锁。

  Threading模块中,也有一个类,RLock,称之为可重入锁。该锁对象内部维护着一个Lock和一个counter对象。counter对象记录了acquire的次数,使得资源可以被多次require。最后,当所有RLock被release后,其他线程才能获取资源。在同一个线程中,RLock.acquire可以被多次调用,利用该特性,可以解决部分死锁问题。

  以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: