首页 > 其他分享 >线程同步之信号量

线程同步之信号量

时间:2024-01-23 12:44:24浏览次数:24  
标签:std 同步 信号量 线程 Semaphore variable condition

目录


Semaphore信号量

在 C++ 中,可以使用std::Semaphore类来实现信号量。信号量可以用于控制对资源的访问,例如限制同时执行任务的线程数量。

在 C++11 中,std::Semaphore类提供了以下常用函数:

  1. Semaphore():构造函数,创建一个信号量对象。

  2. Semaphore(int count):带初始计数的构造函数,可以指定信号量的初始值。

  3. operator int():重载运算符,返回信号量的当前值。

  4. void acquire():获取信号量。如果信号量的值大于 0,则将其减 1,并立即返回;如果信号量的值为 0,则阻塞当前线程,直到有其他线程释放信号量。

  5. void release():释放信号量。将信号量的值加 1,并唤醒一个或多个等待的线程。

  6. bool try_acquire():尝试获取信号量。如果信号量的值大于 0,则将其减 1,并立即返回true;如果信号量的值为 0,则立即返回false,不会阻塞当前线程。

这些函数是std::Semaphore类的常用接口,用于控制对资源的访问。你可以根据需要使用这些函数来实现线程同步和资源管理。

以下是一个使用信号量的简单示例:

#include <iostream>
#include < semaphore>
#include <thread>

std::Semaphore semaphore(5);

void worker() {
    // 获取信号量
    semaphore.acquire();
    std::cout << "Worker acquired a semaphore" << std::endl;
    // 执行工作
    std::this_thread::sleep_for(std::chrono::seconds(1));
    // 释放信号量
    semaphore.release();
    std::cout << "Worker released a semaphore" << std::endl;
}

int main() {
    std::thread threads[10];

    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(worker);
    }

    for (int i = 0; i < 10; ++i) {
        threads[i].join();
    }

    return 0;
}

在上述示例中,创建了一个信号量semaphore,初始值为 5。然后,创建了 10 个工作线程,并让它们循环获取和释放信号量。
通过使用信号量,可以控制同时执行工作的线程数量,确保最多有 5 个线程同时工作。这样可以实现线程池的同步,防止过多的线程同时执行任务。
请注意,std::Semaphore在 C++11 及更高版本中可用。如果你使用的是较旧的 C++ 标准,可以考虑使用其他的信号量实现,例如SystemV信号量。


Semaphore与condition_variable的区别

在 C++11 中,Semaphore(信号量)和condition_variable(条件变量)都是用于线程同步的工具,但它们的用途略有不同。

  • Semaphore用于控制对资源的访问。它提供了一个计数器,可以限制同时访问资源的线程数量。当计数器大于 0 时,线程可以获取资源;当计数器为 0 时,线程将被阻塞,直到有其他线程释放资源。
  • condition_variable用于等待某个条件的发生。它通常与互斥锁一起使用,以确保在条件满足之前,只有一个线程可以执行等待操作。当条件不满足时,等待的线程将被阻塞;当条件满足时,condition_variable会通知一个或多个等待的线程。

简单来说,Semaphore用于限制资源的并发访问,而condition_variable用于等待某个条件的发生。两者通常结合使用,以实现更复杂的线程同步逻辑。

标签:std,同步,信号量,线程,Semaphore,variable,condition
From: https://www.cnblogs.com/yubo-guan/p/17982210

相关文章

  • MySQL线程状态详解
    前言:我们常用showprocesslist或showfullprocesslist查看数据库连接状态,其中比较关注的是State列,此列表示该连接此刻所在的状态。那么你真的了解不同State值所表示的状态吗?下面我们参考官方文档来一探究竟。以MySQL5.7版本为例官方文档地址:https://dev.my......
  • QT笔记:多线程和信号槽
    QT笔记:多线程和信号槽多线程创建多线程有两种方法,一般推荐用moveToThread方法参考代码如下:mainwindow.h#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>#include<QApplication>QT_BEGIN_NAMESPACEnamespaceUi{classMainWindow;}QT_END_NAMES......
  • .NET 6 实现一个任务队列,且在不同线程中调用队列,队列始终都是串行执行
    在.NET6中,要实现一个任务队列,确保队列中的任务始终串行执行,即使它们是由不同线程调用的,你可以使用Channel<T>结合Task.Run或者更简单地使用BlockingCollection<T>与Task.Factory.StartNew或async/await模式。不过,为了保持代码的简洁性和现代性,我会推荐使用Channel<T>结合async/aw......
  • 线程池
    目录简单的线程池简单的线程池在C++11中,你可以使用 std::thread 和 std::mutex 等标准库来实现一个简单的线程池。以下是一个简单的示例代码:#include<iostream>#include<vector>#include<thread>#include<mutex>#include<queue>classThreadPool{private:......
  • java线程池-1
    1.概述Java线程的创建非常昂贵,需要JVM和OS(操作系统)配合完成大量的工作:必须为线程堆栈分配和初始化大量内存块,其中包含至少1MB的栈内存。需要进行系统调用,以便在OS(操作系统)中创建和注册本地线程。Java高并发应用频繁创建和销毁线程的操作将是非常低效的,而且是不被......
  • 一个例子形象的理解同步与异步
    请看一个示例:同步方式请求接口请求一次接口耗时大约100多毫秒代码一个for循环,循环500次,调用方法Reuest,Reuest方法中一个while(true)无限循环,同步方式请求url获取数据。代码点评:要是写一个while(true)没问题,这是是想运行500个while(true),这代码是错误的,行不通。应该使用Thread......
  • mysql8.0主从不一致,重新同步从库
    背景:线上宕机,导致数据不一致,当时为了快速恢复业务,仅使用主库,现在需要恢复,因为主从数据相差比较大,所以对从库重新进行同步。1、首先重置从库的同步设置、并清除从库不一致数据1)#停止slavestopslave;#重置slave,会重置从库相关设置。resetslaveall;2)#清除已同步......
  • SQL Server 2012 AlwaysON 同步延迟时间
     SELECTavailability_mode_desc,role_desc,replica_server_name,last_redone_time,GETDATE()now,DATEDIFF(ms,last_redone_time,GETDATE())diffMSFROM((sys.availability_groupsASagJOINsys.......
  • python 多线程multiprocessing
    该多线程,简单计算结果可以使用,在django里想并行处理多个实体进行计算不行,请自行验证importmultiprocessing#要在进程池中并行执行的任务函数defprocess_data(data):#执行任务的逻辑result=data*2returnresultif__name__=='__main__':#创......
  • C#中Dictionary与ConcurrentDictionary解锁多线程操作安全之道
     使用C#中的Dictionary与ConcurrentDictionary进行多线程操作在C#中,Dictionary是一个常见的字典类型,但它不是线程安全的。为了在多线程环境中确保安全的操作,我们可以使用ConcurrentDictionary,这是一个专门设计用于多线程场景的线程安全字典。1.使用Dictionary进行非线程安......