信号量(Semaphore)是一个同步工具

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 信号量(Semaphore)是一个同步工具

一、信号量(Semaphore)概述

信号量(Semaphore)是一个同步工具,用于控制对共享资源的访问。在Python的threading模块中,Semaphore类提供了一种方式来限制对某个代码块的并发访问数量。信号量内部维护了一个计数器,表示当前可用的资源数量。当计数器大于0时,acquire()方法会将其减1并立即返回,允许线程继续执行。当计数器为0时,acquire()方法会阻塞,直到其他线程调用release()方法增加计数器。

二、Python代码示例

import threading
import time
import random

# 定义一个共享资源,例如一个银行账户
balance = 0

# 定义一个信号量,表示同时访问共享资源的线程数量
semaphore = threading.Semaphore(2)

def withdraw(amount):
    global balance
    # 获取信号量,如果信号量计数器为0,则阻塞
    semaphore.acquire()
    try:
        # 模拟取款操作,这里只是简单地减少余额
        if balance >= amount:
            balance -= amount
            print(f"线程 {threading.current_thread().name} 成功取款 {amount},当前余额为 {balance}")
        else:
            print(f"线程 {threading.current_thread().name} 取款失败,余额不足")
    finally:
        # 释放信号量,无论取款是否成功
        semaphore.release()

def main():
    # 创建多个线程模拟并发取款操作
    for i in range(10):
        amount = random.randint(10, 100)  # 每次取款的金额是随机的
        t = threading.Thread(target=withdraw, args=(amount,), name=f"取款线程{i+1}")
        t.start()

    # 等待所有线程完成
    for t in threading.enumerate():
        if t != threading.current_thread():
            t.join()

    print("所有取款操作完成,最终余额为:", balance)

if __name__ == "__main__":
    main()

三、代码解释

1. 导入必要的模块

  • threading:Python的线程模块,提供了创建和管理线程的功能。
  • time:虽然在这个示例中没有直接使用,但通常用于线程间的同步和延时。
  • random:用于生成随机的取款金额。

2. 定义共享资源和信号量

  • balance:表示银行账户的余额,是一个全局变量,多个线程都会访问和修改它。
  • semaphore:一个threading.Semaphore对象,用于控制同时访问balance的线程数量。这里我们设置计数器为2,表示同时最多有两个线程可以访问balance

3. 定义取款函数

  • withdraw(amount):模拟取款操作。首先,通过调用semaphore.acquire()获取信号量。如果信号量的计数器大于0,则立即返回并继续执行取款逻辑;如果计数器为0,则阻塞等待。取款逻辑完成后(无论是否成功),都通过调用semaphore.release()释放信号量。

4. 主函数

  • main():创建多个线程并启动它们,模拟并发取款操作。每个线程都会调用withdraw()函数进行取款。通过调用t.join()等待所有线程完成。

5. 运行程序

  • 当程序作为主模块运行时(即直接运行这个Python文件而不是作为模块导入),会调用main()函数启动程序。

四、深入讨论

1. 信号量的作用

  • 限制并发访问:通过信号量,我们可以限制同时访问某个共享资源的线程数量,从而避免资源竞争和冲突。
  • 实现同步:信号量提供了一种同步机制,确保在特定时刻只有一个或少数几个线程可以访问共享资源。
  • 防止死锁:与锁(Lock)相比,信号量更灵活,更容易避免死锁。因为信号量允许同时有多个线程访问共享资源,而锁则只允许一个线程访问。

2. 信号量的使用场景

  • 数据库连接池:在Web应用中,为了提高性能和减少资源消耗,通常会使用数据库连接池来管理数据库连接。通过信号量,我们可以限制同时从连接池中获取连接的线程数量。
  • 文件读写:当多个线程需要同时读写同一个文件时,可以使用信号量来确保在任意时刻只有一个线程在写文件,而读文件的线程数量可以稍多一些。
  • 网络请求:在
    处理结果:

    一、信号量(Semaphore)概述

    信号量(Semaphore)是一个同步工具,用于控制对共享资源的访问。在Python的threading模块中,Semaphore类提供了一种方式来限制对某个代码块的并发访问数量。信号量内部维护了一个计数器,表示当前可用的资源数量。当计数器大于0时,acquire()方法会将其减1并立即返回,允许线程继续执行。当计数器为0时,acquire()方法会阻塞,直到其他线程调用release()方法增加计数器。

    二、Python代码示例

    ```python

    定义一个共享资源,例如一个银行账户

    定义一个信号量,表示同时访问共享资源的线程数量

    def withdraw(amount)_
    global balance

    获取信号量,如果信号量计数器为0,则阻塞

    semaphore.acquire()
    try_

    模拟取款操作,这里只是简单地减少余额

    if balance >= amount_
    balance -= amount
    print(f"线程 {threading.currentthread().name} 成功取款 {amount},当前余额为 {balance}")
    else

    print(f"线程 {threading.currentthread().name} 取款失败,余额不足")
    finally

    释放信号量,无论取款是否成功

    semaphore.release()
    def main()_

    创建多个线程模拟并发取款操作

    for i in range(10)_
    amount = random.randint(10, 100) # 每次取款的金额是随机的
    t = threading.Thread(target=withdraw, args=(amount,), name=f"取款线程{i+1}")
    t.start()

    等待所有线程完成

    for t in threading.enumerate()_
    if t != threading.currentthread()
    t.join()
    print("所有取款操作完成,最终余额为:", balance)
    if name == "main"_
    main()

    1. 导入必要的模块

  • threading:Python的线程模块,提供了创建和管理线程的功能。

    2. 定义共享资源和信号量

  • balance:表示银行账户的余额,是一个全局变量,多个线程都会访问和修改它。

    3. 定义取款函数

  • withdraw(amount):模拟取款操作。首先,通过调用semaphore.acquire()获取信号量。如果信号量的计数器大于0,则立即返回并继续执行取款逻辑;如果计数器为0,则阻塞等待。取款逻辑完成后(无论是否成功),都通过调用semaphore.release()释放信号量。

    4. 主函数

  • main():创建多个线程并启动它们,模拟并发取款操作。每个线程都会调用withdraw()函数进行取款。通过调用t.join()等待所有线程完成。

    5. 运行程序

  • 当程序作为主模块运行时(即直接运行这个Python文件而不是作为模块导入),会调用main()函数启动程序。

    四、深入讨论

    1. 信号量的作用

  • 限制并发访问:通过信号量,我们可以限制同时访问某个共享资源的线程数量,从而避免资源竞争和冲突。

    2. 信号量的使用场景

  • 数据库连接池:在Web应用中,为了提高性能和减少资源消耗,通常会使用数据库连接池来管理数据库连接。通过信号量,我们可以限制同时从连接池中获取连接的线程数量。
相关文章
|
5月前
|
存储 Linux 程序员
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
|
5月前
|
安全 算法 Linux
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
|
5月前
|
缓存 Linux 调度
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)
|
5月前
|
算法 安全 Unix
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
151 0
|
5月前
|
安全 算法 Linux
Linux多线程【线程互斥与同步】
Linux多线程【线程互斥与同步】
70 0
|
5月前
|
Linux 数据安全/隐私保护
Linux线程同步(条件变量)
Linux线程同步(条件变量)
60 0
|
5月前
多线程并发之Semaphore(信号量)使用详解
多线程并发之Semaphore(信号量)使用详解
1549 0
|
安全 数据安全/隐私保护
线程互斥、同步(二)
线程互斥、同步
56 1
|
安全 程序员 编译器
线程互斥、同步(一)
线程互斥、同步
81 1
【并发技术14】线程同步工具Semaphore的使用
【并发技术14】线程同步工具Semaphore的使用