python多线程高级锁condition简单用法示例

yizhihongxing

当我们使用python中的多线程编程时,有一些共享的资源需要被不同的线程访问和修改,但是同时又需要保证同一时间只有一个线程能够访问和修改这些共享资源,否则就会出现数据不一致的情况。这时候就需要使用同步机制,而pythond的高级锁Condition就能够很好地完成这项工作。

下面我们来详细介绍一下Condition的使用方法,分别有以下几个方面:

  1. Condition的初始化
  2. Condition的wait方法
  3. Condition的notify方法
  4. Condition的notify_all方法

1. Condition的初始化

在使用Condition时,我们首先需要通过threadin.locks模块中的RLock类创建一个可重入锁,然后再使用这个锁初始化一个Condition对象。下面我们通过代码来演示这个过程:

import threading

# 创建可重入锁
lock = threading.RLock()
# 通过可重入锁初始化Condition对象
condition = threading.Condition(lock)

2. Condition的wait方法

Condition中有一个wait()方法,当线程访问到某个共享资源时,如果该资源不可用,则调用wait()方法自动阻塞线程,直到该资源可用时再被唤醒。同时,在调用wait()方法之前需要获取关联的锁,否则会抛出RuntimeError异常。

下面我们来看一个简单的示例,假设有两个线程分别需要同时访问一个共享资源resource,并且如果resource已经被其中一个线程占用,则另一个线程需要等待,等到resource被释放后才能够继续访问。这个过程可以通过下面的代码来实现:

import threading
import time

# 创建可重入锁
lock = threading.RLock()
# 通过可重入锁初始化Condition对象
condition = threading.Condition(lock)

# 共享资源
resource = 0

# 线程1
def thread1():
    global resource
    with lock:
        # 如果resource已经被占用则等待
        while resource != 0:
            condition.wait()
        # 将resource占用
        resource = 1
        print("Thread 1: get resource")
        time.sleep(2)
        # 释放resource
        resource = 0
        print("Thread 1: release resource")
        condition.notify()

# 线程2
def thread2():
    global resource
    with lock:
        # 如果resource已经被占用则等待
        while resource != 0:
            condition.wait()
        # 将resource占用
        resource = 2
        print("Thread 2: get resource")
        time.sleep(2)
        # 释放resource
        resource = 0
        print("Thread 2: release resource")
        condition.notify()

t1 = threading.Thread(target=thread1)
t2 = threading.Thread(target=thread2)

t1.start()
t2.start()

上面的代码中,线程1和线程2分别使用了wait()方法等待resource变为可用,并且在获取到resource后进行了一段耗时的操作,最后释放该资源,同时通过调用notify()方法唤醒其它等待该资源的线程。

3. Condition的notify方法

当某个线程完成共享资源的修改后,需要唤醒等待该资源的线程,这时候就可以调用notify()方法解除一个等待该资源的线程的阻塞,使其可以继续执行。需要注意的是,如果当前有多个线程等待该资源,那么调用notify()方法只会解除其中的一个线程的阻塞,如果要唤醒全部等待该资源的线程,可以使用notify_all()方法。

下面我们再来看一个示例,假设有多个线程需要同时访问一个限流器,但是限流器同一时间只允许一个线程进行访问,如果超过限制则需要等待,这个过程可以通过下面的代码来实现:

import threading

# 创建可重入锁
lock = threading.RLock()
# 通过可重入锁初始化Condition对象
condition = threading.Condition(lock)

# 限流器,一次只允许一个线程访问
rate_limiter = threading.Semaphore(1)

# 线程
def worker(worker_id):
    # 访问限流器
    rate_limiter.acquire()
    print("Thread {} get rate limiter".format(worker_id))
    # 释放限流器
    rate_limiter.release()

    with lock:
        # 通知其它等待该资源的线程可以开始执行
        condition.notify()

    print("Thread {} start working".format(worker_id))
    # 模拟耗时的操作
    time.sleep(1)
    print("Thread {} finish working".format(worker_id))

threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)

for t in threads:
    t.start()

在上面的代码中,通过Semaphore限制了同时访问限流器的线程数为1,当一个线程成功获取限流器后才能够对共享资源进行访问,如果有其它线程需要访问,那么就需要在wait()方法等待,当当前线程完成对共享资源的访问后,释放限流器并且通过notify()方法通知其它等待该资源的线程可以开始执行。

4. Condition的notify_all方法

notify_all()方法和notify()方法类似,不同的是它能够唤醒所有等待该资源的线程。下面我们通过简单的示例来演示这个过程,假设有多个线程需要同时访问一个"桥",但是桥只能容纳一辆车通过,如果当前桥上有车,则其它车辆需要等待,这个过程可以通过下面的代码来实现:

import threading

# 创建可重入锁
lock = threading.RLock()
# 通过可重入锁初始化Condition对象
condition = threading.Condition(lock)

# 资源
bridge = 0

# 线程
def worker(worker_id):
    global bridge
    with lock:
        # 如果当前桥有车,则需要等待
        while bridge != 0:
            condition.wait()
        # 过桥
        bridge = 1
        print("Car {} passed the bridge".format(worker_id))
        # 离开桥
        bridge = 0
        # 唤醒其它车辆继续过桥
        condition.notify_all()

threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)

for t in threads:
    t.start()

在上面的代码中,如果当前桥上有车,则需要等待,当桥被当前车辆通过后离开,并且唤醒其它等待该资源的车辆通过。这个过程可以通过notify_all()方法实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python多线程高级锁condition简单用法示例 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 爬山算法简介和Python实现实例

    爬山算法简介和Python实现实例 爬山算法简介 爬山算法(Hill Climbing Algorithm)是一种简单且常用的启发式优化算法。该算法的基本思想是从当前解出发,每次搜索邻域中比当前解更优的解,直到达到一个局部最优解。 但是,爬山算法容易陷入局部最优解,并且不能保证找到全局最优解。因此,在实际应用中常常会利用多次随机化生成多个初始解,或者使用其他…

    python 2023年5月19日
    00
  • Python语法之精妙的十个知识点(装B语法)

    这里是完整攻略。 Python语法之精妙的十个知识点(装B语法) 1. 列表生成式(List Comprehensions) 列表生成式是用来快速生成一个列表的简洁语法。它的基本形式是:[expression for item in iterable]。其中 expression 是一个任意的 Python 表达式,item 是可迭代对象 iterable …

    python 2023年5月13日
    00
  • python中常用的内置模块汇总

    让我来给你详细介绍一下Python中常用的内置模块。 什么是Python内置模块 Python内置模块是指Python语言之中自带的标准库。Python标准库是Python语言的核心组成部分,提供了诸多常用的功能模块,如IO操作、字符串处理、正则表达式、数学运算、日期时间以及网络通信等各种工具。Python内置模块可以直接导入使用,不需要额外安装其他第三方模…

    python 2023年5月30日
    00
  • Python面向对象编程基础解析(一)

    针对“Python面向对象编程基础解析(一)”这篇文章,以下是详细的攻略: Python面向对象编程基础解析(一)——概念篇 1. 什么是面向对象编程(Object-oriented Programming)? 首先,本文对面向对象编程的定义进行了介绍,即,将数据和操作数据的方法封装在一起,形成一个对象。在面向对象编程中,我们对于对象中的数据和方法的访问是通…

    python 2023年5月13日
    00
  • 利用Python如何生成hash值示例详解

    下面是详细的攻略。 利用Python生成hash值 什么是hash值 hash值也称散列值,是一种将任意长度的消息压缩到某一固定长度的数字指纹的函数。简单说,就是通过hash函数算法,将原始数据转换成一段唯一的数字串。 hash值有以下特点: 任意长度的输入都可以得到固定长度输出; 不同的输入得到的hash值应尽量不同; 相同的输入得到的hash值必须相同。…

    python 2023年6月2日
    00
  • hmac模块生成加入了密钥的消息摘要详解

    下面我将详细讲解如何使用hmac模块生成加入了密钥的消息摘要。 什么是HMAC? HMAC是一种通过散列算法构造的消息认证码。它是一种基于密钥的哈希算法,可以用于验证消息的完整性,同时也可以用于身份认证。 HMAC的算法流程 生成HMAC需要先准备一个密钥和一条消息。下面是HMAC的算法流程: 如果密钥的长度比HASH函数的块长要长,则使用HASH函数对密钥…

    python 2023年6月3日
    00
  • Python 列表 vs C 数组:慢 100 倍? [关闭]

    【问题标题】:Python lists vs C arrays : 100x slower? [closed]Python 列表 vs C 数组:慢 100 倍? [关闭] 【发布时间】:2023-04-06 12:12:01 【问题描述】: 据我了解,Python 列表是作为向量实现的。这就是为什么我无法解释为什么以下代码在 Python 中比等效的 C …

    Python开发 2023年4月6日
    00
  • Python文件夹与文件的操作实现代码

    下面是Python文件夹与文件的操作实现代码的完整攻略。 1. 获取文件路径 对于文件夹和文件的操作,首先需要获取其路径。Python提供了os库来进行路径操作。 获取当前文件夹路径 import os current_dir = os.getcwd() print(f"当前文件夹路径为:{current_dir}") 上述代码使用get…

    python 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部