首页 > 编程语言 >python多线程中锁的概念 threading.Lock

python多线程中锁的概念 threading.Lock

时间:2023-09-18 15:46:45浏览次数:51  
标签:__ 中锁 Thread lock counter threading 线程 多线程

https://blog.csdn.net/qq_21439971/article/details/79356248

 

python的锁可以独立提取出来

1 2 3 4 5 6 7 8 mutex  =  threading.Lock() #锁的使用 #创建锁 mutex  =  threading.Lock() #锁定 mutex.acquire([timeout]) #释放 mutex.release()

概念

好几个人问我给资源加锁是怎么回事,其实并不是给资源加锁, 而是用锁去锁定资源,你可以定义多个锁, 像下面的代码, 当你需要独占某一资源时,任何一个锁都可以锁这个资源

就好比你用不同的锁都可以把相同的一个门锁住是一个道理

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import   threading    import   time           counter  =  0  counter_lock  =  threading.Lock()  #只是定义一个锁,并不是给资源加锁,你可以定义多个锁,像下两行代码,当你需要占用这个资源时,任何一个锁都可以锁这个资源  counter_lock2  =  threading.Lock()   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   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,锁。我们创建一个该类对象,在线程函数执行前,“抢占”该锁,执行完成后,“释放”该锁,则我们确保了每次只有一个线程占有该锁。这时候对一个公共的对象进行操作,则不会发生线程不安全的现象了。

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 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               + =  1              lock.release() if  "__main__"  = =  __name__:       =  1      ThreadList  =  []      lock  =  threading.Lock()      for   in  range ( 1  200 ):           =  MyThread()          ThreadList.append(t)      for   in  ThreadList:          t.start()      for   in  ThreadList:          t.join()
1 2 3 4 5 6 7 8 9 10 11 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可以被多次调用,利用该特性,可以解决部分死锁问题。

标签:__,中锁,Thread,lock,counter,threading,线程,多线程
From: https://www.cnblogs.com/shuimuqingyang/p/17712108.html

相关文章

  • python多线程
    Python多线程参考文章:python多线程详解(超详细)、Python线程池(threadpool)创建及使用+实例代码、第二十章多线程1、多线程的概念2、python多线程的基本使用方法3、多线程的优点及与多进程的关系1、多线程的概念线程也叫轻量级进程,是操作系统能够进行运算调度......
  • 利用SharedArrayBuffer进行多线程编程
    利用SharedArrayBuffer进行多线程编程在现代Web应用程序中,性能是一个至关重要的因素。为了提高Web应用程序的性能,我们经常需要执行并行计算,例如图像处理、音频处理或数据分析。在这种情况下,多线程编程是一种强大的工具,它允许我们充分利用多核处理器。然而,多线程编程并不是一件容易......
  • .NET中测量多线程基准性能
    .NET中测量多线程基准性能 多线程基准性能是用来衡量计算机系统或应用程序在多线程环境下的执行能力和性能的度量指标。它通常用来评估系统在并行处理任务时的效率和性能。测量中通常创建多个线程并在这些线程上执行并发任务,以模拟实际应用程序的并行处理需求。在此,我们用多......
  • 深入了解信号量:多线程同步的得力工具
    随着计算机科学和软件工程的不断发展,多线程编程变得越来越重要。多线程允许程序同时执行多个任务,提高了程序的效率和性能。然而,多线程编程也引入了新的问题,例如竞态条件和数据竞争。为了解决这些问题,同步工具变得至关重要,而信号量是其中一个强大的工具。什么是信号量?信号量是一......
  • Java多线程学习(Day01)
    目录线程简介线程实现(重点)线程状态线程同步(重点)线程通信问题进程与线程概念                                     --来自百度百科的解释:        进程(Process)是......
  • CompletableFuture 异步多线程D优雅!
    一个示例回顾Future一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。JDK5新增了Future接口,用于描述一个异步计算的结果。虽然Future以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮......
  • 远程调用优化之多线程
    1.通过feign进行远程调用是一种同步调用,只有当一个远程调用执行完毕以后,才会进行下一个远程调用,效率较低。2.可以考虑业务的执行逻辑,如果各个远程调用之间互不影响的话,可以考虑使用多线程来进行优化,提高效率。1.配置线程池1.1在公共的微服务中编写ThreadPoolConfiguration......
  • 25届实习秋招-Java面试-JUC多线程面试题整理-牛客网
    JUC介绍一下JUC下的锁(如何使用及应用场景)线程什么是进程:特征什么是线程:资源为什么多线程,什么使用用单线程,什么时候多线程,什么条件下多线程快。进程和线程的对比:进程如何通信,每种通信存放的介质。||线程的通信,几种方式。join进程和线程的区别,在JVM层面的体现一......
  • .Net多线程读取pdf文本
    1.nuget安装UglyToad.PdfPig2.SemaphoreSlimsemaphore=newSemaphoreSlim(10);同时启动10个线程读取指定页面文本。C#代码:staticstringGetPdfText(stringfilePath){FileInfofile=newFileInfo(filePath);if(file.Extension.ToLower().Contains("pdf"))......
  • 记录一个python多线程的错误写法
    直接先上错误代码:importmultiprocessingdeffirst_way():init=3defprocess_function(item):result=item*initreturnresultdata=[1,2,3,4,5,6,7,8,9,10]pool=multiprocessing.Pool(processes=4)#创建一个......