【python】详解threading模块:lock、Rlock的使用(二)

2023-05-16

在之前的【python】详解threading模块:基本概念、join阻塞和setDaemon守护主线程(一)一文中,是有对多线程进行一个详细的梳理的。其中就提到了线程锁这一功能。主要基于Rlock实现。本文将进一步总结,丰富线程锁内容。

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

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

1、Lock(互斥锁)

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

Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。
可以认为Lock有一个锁定池,当线程请求锁定时,将线程至于池中,直到获得锁定后出池。池中的线程处于状态图中的同步阻塞状态。
构造方法:mylock = Threading.Lock( )
实例方法:

  1. acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。
  2. 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,保证成对出现
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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【python】详解threading模块:lock、Rlock的使用(二) 的相关文章

  • numba 函数何时编译?

    我正在研究这个例子 http numba pydata org numba doc 0 15 1 examples html multi threading http numba pydata org numba doc 0 15 1 ex
  • Spark 请求最大计数

    我是 Spark 的初学者 我尝试请求允许我检索最常访问的网页 我的要求如下 mostPopularWebPageDF logDF groupBy webPage agg functions count webPage alias cntW
  • 使用 python 进行串行数据记录

    Intro 我需要编写一个小程序来实时读取串行数据并将其写入文本文件 我在读取数据方面取得了一些进展 但尚未成功地将这些信息存储在新文件中 这是我的代码 from future import print function import se
  • Python模块可以访问英语词典,包括单词的定义[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 python 模块 它可以帮助我从英语词典中获取单词的定义 当然有enchant 这可以帮助我检查该单词是否存在于英语中
  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • 将数据帧行转换为字典

    我有像下面的示例数据这样的数据帧 我正在尝试将数据帧中的一行转换为类似于下面所需输出的字典 但是当我使用 to dict 时 我得到了索引和列值 有谁知道如何将行转换为像所需输出那样的字典 任何提示都非常感激 Sample data pri
  • 以同步方式使用 FastAPI,如何获取 POST 请求的原始正文?

    在中使用 FastAPIsync not async模式 我希望能够接收 POST 请求的原始 未更改的正文 我能找到的所有例子都显示async代码 当我以正常同步方式尝试时 request body 显示为协程对象 当我通过发布一些内容来
  • 在Python中调整图像大小

    我有一张尺寸为 288 352 的图像 我想将其大小调整为 160 240 我尝试了以下代码 im imread abc png img im resize 160 240 Image ANTIALIAS 但它给出了一个错误TypeErro
  • 使用 OLS 回归预测未来值(Python、StatsModels、Pandas)

    我目前正在尝试在 Python 中实现 MLR 但不确定如何将我找到的系数应用于未来值 import pandas as pd import statsmodels formula api as sm import statsmodels
  • Python urllib.request.urlopen:AttributeError:'bytes'对象没有属性'data'

    我正在使用 Python 3 并尝试连接到dstk 我收到错误urllib包裹 我对SO进行了很多研究 但找不到与这个问题类似的东西 api url self api base street2coordinates api body jso
  • 从 python 发起 SSH 隧道时出现问题

    目标是在卫星服务器和集中式注册数据库之间建立 n 个 ssh 隧道 我已经在我的服务器之间设置了公钥身份验证 因此它们只需直接登录而无需密码提示 怎么办 我试过帕拉米科 它看起来不错 但仅仅建立一个基本的隧道就变得相当复杂 尽管代码示例将受
  • 使用鼻子获取设置中当前测试的名称

    我目前正在使用鼻子编写一些功能测试 我正在测试的库操作目录结构 为了获得可重现的结果 我存储了一个测试目录结构的模板 并在执行测试之前创建该模板的副本 我在测试中执行此操作 setup功能 这确保了我在测试开始时始终具有明确定义的状态 现在
  • Numpy 过滤器平滑零区域

    我有一个 0 及更大整数的 2D numpy 数组 其中值代表区域标签 例如 array 9 9 9 0 0 0 0 1 1 1 9 9 9 9 0 7 1 1 1 1 9 9 9 9 0 2 2 1 1 1 9 9 9 8 0 2 2 1
  • Python 将日志滚动到变量

    我有一个使用多线程并在服务器后台运行的应用程序 为了无需登录服务器即可监控应用程序 我决定包括Bottle http bottlepy org为了响应一些HTTP端点并报告状态 执行远程关闭等 我还想添加一种查阅日志文件的方法 我可以使用以
  • 使用 Firefox 绕过弹出窗口下载文件:Selenium Python

    我正在使用 selenium 和 python 来从中下载某些文件web page http www oceanenergyireland com testfacility corkharbour observations 我之前一直使用设
  • Ubuntu 上的 Python 2.7

    我是 Python 新手 正在 Linux 机器 Ubuntu 10 10 上工作 它正在运行 python 2 6 但我想运行 2 7 因为它有我想使用的功能 有人敦促我不要安装 2 7 并将其设置为我的默认 python 我的问题是 如
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 在Python中按属性获取对象列表中的索引

    我有具有属性 id 的对象列表 我想找到具有特定 id 的对象的索引 我写了这样的东西 index 1 for i in range len my list if my list i id specific id index i break
  • Elastic Beanstalk 中的 enum34 问题

    我正在尝试在 Elastic Beanstalk 中设置 django 环境 当我尝试通过requirements txt 文件安装时 我遇到了python3 6 问题 File opt python run venv bin pip li
  • 列表值的意外更改

    这是我的课 class variable object def init self name name alias parents values table name of the variable self name 这是有问题的函数 f

随机推荐

  • datax 同步mongodb数据库到hive(hdfs)和elasticserch(es)

    一 同步环境 1 mongodb版本 xff1a 3 6 3 xff08 有点老了 xff0c 后来发现flinkcdc都只能监控一张表 xff0c 多张表无法监控 xff09 2 datax版本 xff1a 自己编译的DataX data
  • Qt播放音视频文件报错DirectShowPlayerService::doRender: Unresolved error code 0x80040266或DirectShowPlayerServi

    Qt播放音视频文件报错DirectShowPlayerService doRender Unresolved error code 0x80040266或DirectShowPlayerService doSetUrlSource Unre
  • 基本图形的绘制与填充

    span class token macro property span class token directive hash span span class token directive keyword ifndef span span
  • 2D坐标变换

    span class token macro property span class token directive hash span span class token directive keyword ifndef span span
  • c++中常量的两种定义方式

    常量是定以后 xff0c 在程序运行中不能被改变的标识符 C 43 43 中定义常量可以用 define const 这两种方法 例如 define PRICE 10 定义单价常量10 const int PRICE 61 10 定义单价常
  • c++中的floor, ceil, round

    xfeff xfeff 2 1 2 6 2 1 2 6 floor 不大于自变量的最大整数 2 2 3 3 ceil 不小于自变量的最小整数 3 3 2 2 round 四舍五入到最邻近的整数 2 3 2
  • 用conat修饰的类成员——常成员函数、常成员数据、常引用

    xfeff xfeff include lt iostream gt include lt cstdlib gt using namespace std class R public R int r1 int r2 m iR1 r1 m i
  • 对象的生存期——变量的生存期与可见性

    include lt iostream gt using namespace std int i 61 1 i为全局变量 xff0c 具有静态生存期 void other a b是静态局部变量 xff0c 具有静态生存期 xff0c 局部可
  • 类的友元

    include lt iostream gt include lt cstdlib gt using namespace std class Point public Point int x int y friend float dist
  • 树莓派全系列对比

    树莓派全系列参数介绍如下 xff1a 再附上 知乎 64 少数派 的一张图 xff1a Raspberry官网对过去使用的博通Soc的描述 BCM2837B0 This is the Broadcom chip used in the Ra
  • Runtime类

    xfeff xfeff 在每一个java应用程序中 xff0c 都有唯一一个RunTime对象 xff0c 该唯一的RunTime对象可通过getRunTime 方法获得 应用程序不能创建自己的RunTime队象 xff0c package
  • 动态二维数组

    include lt iostream gt include lt cstdlib gt using namespace std class Point public Point cout lt lt 34 执行无参构造函数 34 lt l
  • 获得服务器硬件信息(CPUID、硬盘号、主板序列号、IP地址等)

    获得服务器硬件信息 xff08 CPUID 硬盘号 主板序列号 IP地址等 xff09 linux命令 获取IP地址 ifconfig a 获取CPU信息 dmidecode t processor grep ID lscpu cat pr
  • MySQL备份和还原操作

    MySQL备份和还原操作 目标 备份的概念 Mysqldump备份操作 MySQL还原操作 MySQL双机热备份 概述 在数据库表丢失或损坏的情况下 xff0c 备份数据库是很重要的 如果发生系统崩溃 xff0c 能够将表尽可能丢失最少的数
  • MySQL性能优化

    MySQL性能优化 目标 调优思路系统优化mysql服务优化应用优化方式SQL语句调优启用mysql慢查询 调优思路 数据库设计与规划 以后再修该很麻烦 xff0c 估计数据量 xff0c 使用什么存储引擎数据的应用 怎样取数据 xff0c
  • Hadoop伪分布模式安装

    Hadoop伪分布模式安装 Hadoop的运行模式分为3种 xff1a 本地运行模式 xff0c 伪分布运行模式 xff0c 完全分布运行模式 xff08 1 xff09 本地模式 xff08 local mode xff09 这种运行模式
  • 云的几种部署模式

    云的几种部署模式 定义 xff1a 特点云的部署模式 定义 xff1a 云 是一种计算模式 xff0c 利用互联网技术把大量可扩展和弹性的IT相关能力作为 一种服务提供给多个客户 特点 服务化 弹性 多租户 云的部署模式 公有云 混合云 内
  • 通过git 上传本地代码至码云

    实验步骤 1 配置ssh xff08 1 xff09 在本地生成sshkey xff0c 打开git命令终端 git bash 窗口 ssh keygen t rsa C 34 xxxxx 64 xxxxx com 34 你的邮箱 xff0
  • git常见命令

    常见命令 1 初始化本地仓库 git init 2 需要与码云保持一致 git config global user name 34 用户姓名 34 git config global user email 34 用户邮箱 34 3 设置远
  • 【python】详解threading模块:lock、Rlock的使用(二)

    在之前的 python 详解threading模块 xff1a 基本概念 join阻塞和setDaemon守护主线程 xff08 一 xff09 一文中 xff0c 是有对多线程进行一个详细的梳理的 其中就提到了线程锁这一功能 主要基于Rl