Python threading模块中lock与Rlock的使用详细讲解

目录
  • 前言
  • 1、Lock(互斥锁)
  • 2、RLock(可重入锁)

前言

在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock 、Rlock 、Semaphore 、Event 、Condition 用来保证线程之间的同步,后者保证访问共享变量的互斥问题。

  • Lock & RLock:互斥锁,用来保证多线程访问共享变量的问题
  • Semaphore对象:Lock互斥锁的加强版,可以被多个线程同时拥有,而Lock只能被某一个线程同时拥有。
  • Event对象:它是线程间通信的方式,相当于信号,一个线程可以给另外一个线程发送信号后让其执行操作。
  • Condition对象:其可以在某些事件触发或者达到特定的条件后才处理数据

1、Lock(互斥锁)

请求锁定 — 进入锁定池等待 — — 获取锁 — 已锁定— — 释放锁

Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。

可以认为Lock有一个锁定池,当线程请求锁定时,将线程至于池中,直到获得锁定后出池。池中的线程处于状态图中的同步阻塞状态。

构造方法:mylock = Threading.Lock( )

实例方法:

  • acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。
  • release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。

实例一(未使用锁):

import threading
import time
num = 0
def show(arg):
    global num
    time.sleep(1)
    num +=1
    print('bb :{}'.format(num))
for i in range(5):
    t = threading.Thread(target=show, args=(i,))  # 注意传入参数后一定要有【,】逗号
    t.start()
print('main thread stop')

main thread stop
bb :1
bb :2
bb :3bb :4
bb :5

实例二(使用锁)

import threading
import time
num = 0
lock = threading.RLock()
# 调用acquire([timeout])时,线程将一直阻塞,
# 直到获得锁定或者直到timeout秒后(timeout参数可选)。
# 返回是否获得锁。
def Func():
    lock.acquire()
    global num
    num += 1
    time.sleep(1)
    print(num)
    lock.release()
for i in range(10):
    t = threading.Thread(target=Func)
    t.start()

1
2
3
4
5
6
7
8
9
10
#可以看出,全局变量在在每次被调用时都要获得锁,才能操作,因此保证了共享数据的安全性

对于Lock对象而言,如果一个线程连续两次release,使得线程死锁。所以Lock不常用,一般采用Rlock进行线程锁的设定。

import threading
import time
class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)
        if lock.acquire(1):
            num = num+1
            msg = self.name+' set num to '+str(num)
            print(msg)
            lock.acquire()
            lock.release()
            lock.release()
num = 0
lock = threading.Lock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()
Thread-12 set num to 1

2、RLock(可重入锁)

RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了“拥有的线程”和“递归等级”的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用 acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。

  • 构造方法:mylock = Threading.RLock()
  • 实例方法:acquire([timeout])/release(): 跟Lock差不多。

实例解决死锁,调用相同次数的acquire和release,保证成对出现

'''
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import threading
rLock = threading.RLock()  #RLock对象
rLock.acquire()
rLock.acquire() #在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()
print(rLock.acquire())

详细实例:

import threading
mylock = threading.RLock()
num = 0
class WorkThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.t_name = name
    def run(self):
        global num
        while True:
            mylock.acquire()
            print('\n%s locked, number: %d' % (self.t_name, num))
            if num >= 2:
                mylock.release()
                print('\n%s released, number: %d' % (self.t_name, num))
                break
            num += 1
            print('\n%s released, number: %d' % (self.t_name, num))
            mylock.release()
def test():
    thread1 = WorkThread('A-Worker')
    thread2 = WorkThread('B-Worker')
    thread1.start()
    thread2.start()
if __name__ == '__main__':
    test() 

A-Worker locked, number: 0

A-Worker released, number: 1

A-Worker locked, number: 1

A-Worker released, number: 2

A-Worker locked, number: 2

A-Worker released, number: 2

B-Worker locked, number: 2

B-Worker released, number: 2

到此这篇关于Python threading模块中lock与Rlock的使用详细讲解的文章就介绍到这了,更多相关Python threading内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 对python多线程中互斥锁Threading.Lock的简单应用详解

    一.线程共享进程资源 每个线程互相独立,相互之间没有任何关系,但是在同一个进程中的资源,线程是共享的,如果不进行资源的合理分配,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为"线程不安全". 实例如下: #-*- coding: utf-8 -*- import threading import time def test_xc(): f = open("test.txt","a") f.write("test_dxc&quo

  • python多线程threading.Lock锁用法实例

    本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 复制代码 代码如下: mutex = threading.Lock() #锁的使用 #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([timeout]) #释放 mutex.release() 锁定方法acquire可以有一个超时时间的可选参数timeout.如果设定了timeout,则在超时后通过返回值

  • python中的多线程锁lock=threading.Lock()使用方式

    目录 多线程锁lock=threading.Lock()使用 疑问 解决方法 例子 python多线程中锁的概念 锁可以独立提取出来 概念 线程不安全 线程锁 多线程锁lock=threading.Lock()使用 疑问 多线程任务是同时执行的,如果我们需要先执行线程a,再执行线程b,需要怎么办呢? 解决方法 使用python的多线程锁lock. 例子 未使用多线程锁lock: def a():     for i in range(3):         print('a%d' % (i +

  • Python threading中lock的使用详解

    在多线程中使用lock可以让多个线程在共享资源的时候不会“乱”,例如,创建多个线程,每个线程都往空列表l中添加一个数字并打印当前的列表l,如果不加锁,就可能会这样: # encoding=utf8 import threading import time lock = threading.Lock() l = [] def test1(n): lock.acquire() l.append(n) print l lock.release() def test(n): l.append(n) pr

  • Python threading模块中lock与Rlock的使用详细讲解

    目录 前言 1.Lock(互斥锁) 2.RLock(可重入锁) 前言 在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock .Rlock .Semaphore .Event .Condition 用来保证线程之间的同步,后者保证访问共享变量的互斥问题. Lock & RLock:互斥锁,用来保证多线程访问共享变量的问题 Semaphore对象:Lock

  • Python THREADING模块中的JOIN()方法深入理解

    看了oschina上的两个代码,受益匪浅.其中对join()方法不理解,看python官网文档的介绍: join([timeout]):等待直到进程结束.这将阻塞正在调用的线程,直到被调用join()方法的线程结束.(好难翻译,应该是这个意思) 哈哈,这个易懂. join方法,如果一个线程或者一个函数在执行过程中要调用另外一个线程,并且待到其完成以后才能接着执行,那么在调用这个线程时可以使用被调用线程的join方法. 复制代码 代码如下: #-*- encoding: gb2312 -*- im

  • 对python多线程中Lock()与RLock()锁详解

    资源总是有限的,程序运行如果对同一个对象进行操作,则有可能造成资源的争用,甚至导致死锁 也可能导致读写混乱 锁提供如下方法: 1.Lock.acquire([blocking]) 2.Lock.release() 3.threading.Lock() 加载线程的锁对象,是一个基本的锁对象,一次只能一个锁定,其余锁请求,需等待锁释放后才能获取 4.threading.RLock() 多重锁,在同一线程中可用被多次acquire.如果使用RLock,那么acquire和release必须成对出现,

  • Python+threading模块对单个接口进行并发测试

    本文实例为大家分享了Python threading模块对单个接口进行并发测试的具体代码,供大家参考,具体内容如下 本文知识点 通过在threading.Thread继承类中重写run()方法实现定制输出结果 代码如下 import requests import threading import sys, io # 解决console显示乱码的编码问题 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') clas

  • python threading模块的使用指南

    1. threding模块创建线程对象 接上述案例,我们可以利用程序阻塞的时间让程序执行后面的任务,可以用多线程的方式去实现.对应的需要我们借助threading模块去实现: 如下所示 import time import threading def work(): """只有函数对象才能佈田名线积""" print('5.洗茶杯: 1min ' ) time.sleep(1) print('6.放茶叶: 1min ' ) time.sleep(

  • 详解python时间模块中的datetime模块

    Python提供了多个内置模块用于操作日期时间,像calendar,time,datetime.time模块我在之前的文章已经有所介绍,它提供的接口与C标准库time.h基本一致.相比于time模块,datetime模块的接口则更直观.更容易调用. 1.datetime中包含三个类date ,time,datetime 函数datetime.combine(date,time)可以得到dateime,datetime.date().datetime.time()可以获得date和time 2.d

  • python模块中判断全局变量的赋值的实例讲解

    1.在模块中,我们需要判断__name__是否被赋值为"__main__". python fibo.py <arguments> 2.在脚本执行的情况下,模块的__name__属性将被赋值为__main__,这就是原因所在. $ python fibo.py 50 0 1 1 2 3 5 8 13 21 34 3.若以模块导入,则不会执行: >>> import fibo >>> 知识点扩展: Python动态声明变量赋值代码实例 通过

  • python copy模块中的函数实例用法

    1.copy.copy()函数可用于复制列表或字典等可变值,复制后的列表和原列表是两个独立的列表. import copy origin = [1,2,3] new = copy.copy(origin) new[0] = 0 print("origin = ",origin) print("new = ",new) 2.如果要复制的列表中有列表,则使用deepcopy()函数完全复制. import copy origin =[[1,2,3],['a','b','

  • Python 使用PIL中的resize进行缩放的实例讲解

    今天突然发现自己缩放程序有问题,图片缩放尺度大了就会失真.小编一直使用的是缩小的功能,图片缩小整体0.7还可以,整体缩小0.65就会有部分的信息丢失,怎奈我的图都是大图,没办法只能寻找解决方法. 原来代码 img = img.resize((width, height)) 后来找资料发现 PIL带ANTIALIAS滤镜缩放结果 所以将代码改为: img = img.resize((width, height),Image.ANTIALIAS) 以上这篇Python 使用PIL中的resize进行

  • Python Flask实现图片验证码与邮箱验证码流程详细讲解

    目录 1. 图片验证码 1.1 工具类-utility.py 1.2 控制层-user.py 2. 邮箱验证码 2.1 准备 2.2 工具类-utility.py 2.3 控制层-user.py 1. 图片验证码 1.1 工具类-utility.py 将所有和图片验证码有关的方法放在类 ImageCode import random import string from io import BytesIO from PIL import Image, ImageFont, ImageDraw c

随机推荐