信号量Semaphore

2024-04-20 02:36
文章标签 信号量 semaphore

本文主要是介绍信号量Semaphore,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是信号量?

C++中的信号量(Semaphore)是一种同步对象,用于控制对共享资源的访问,以防止多个线程或进程同时访问同一资源,从而避免数据不一致的问题。信号量通过维护一个计数值来实现这一功能,该计数值表示可以同时访问共享资源的线程或进程的数量。当一个线程或进程想要访问共享资源时,它会尝试减少信号量的计数值;如果计数值大于零,线程或进程可以继续执行,否则它必须等待直到信号量的计数值变为正数。当线程或进程完成对共享资源的访问后,它会释放信号量,即增加计数值,从而可能允许其他正在等待的线程或进程继续执行。

信号量可以干什么?

  1. 互斥
  2. 限制并发访问
  3. 线程同步
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 1) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mutex_);++count_;condition_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mutex_);while (count_ <= 0) {condition_.wait(lock);}--count_;}private:std::mutex mutex_;std::condition_variable condition_;int count_;
};// 共享资源
int sharedResource = 0;void workerFunction(Semaphore& semaphore) {for (int i = 0; i < 1000; ++i) {semaphore.wait(); // 加锁++sharedResource;semaphore.notify(); // 解锁}
}//实现互斥int main() {Semaphore semaphore(1);std::vector<std::thread> threads;// 创建 10 个工作线程for (int i = 0; i < 10; ++i) {threads.push_back(std::thread(workerFunction, std::ref(semaphore)));}// 等待所有线程完成for (auto& thread : threads) {thread.join();}std::cout << "Shared resource value: " << sharedResource << std::endl;return 0;
}
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 1) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mutex_);++count_;condition_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mutex_);while (count_ <= 0) {condition_.wait(lock);}--count_;}private:std::mutex mutex_;std::condition_variable condition_;int count_;
};void workerFunction(int threadId, Semaphore& semaphore) {semaphore.wait(); // 获取访问权限std::cout << "Thread " << threadId << " is accessing the shared resource." << std::endl;// 模拟访问共享资源std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Thread " << threadId << " has finished accessing the shared resource." << std::endl;semaphore.notify(); // 释放访问权限
}//限制并发访问int main() {Semaphore semaphore(3); // 允许最多3个线程同时访问std::vector<std::thread> threads;// 创建10个工作线程for (int i = 0; i < 10; ++i) {threads.push_back(std::thread(workerFunction, i, std::ref(semaphore)));}// 等待所有线程完成for (auto& thread : threads) {thread.join();}return 0;
}
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 1) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mutex_);++count_;condition_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mutex_);while (count_ <= 0) {condition_.wait(lock);}--count_;}private:std::mutex mutex_;std::condition_variable condition_;int count_;
};void task1(Semaphore& semaphore1, Semaphore& semaphore2) {std::cout << "Task 1 is executing." << std::endl;// 模拟任务执行std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Task 1 is completed." << std::endl;// 通知任务2可以开始执行semaphore1.notify();// 等待任务2完成// semaphore2.wait();
}void task2(Semaphore& semaphore1, Semaphore& semaphore2) {// 等待任务1完成semaphore1.wait();std::cout << "Task 2 is executing." << std::endl;// 模拟任务执行std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Task 2 is completed." << std::endl;// 通知任务3可以开始执行semaphore2.notify();
}void task3(Semaphore& semaphore2) {// 等待任务2完成semaphore2.wait();std::cout << "Task 3 is executing." << std::endl;// 模拟任务执行std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Task 3 is completed." << std::endl;
}//线程同步int main() {Semaphore semaphore1(0), semaphore2(0);std::thread t1(task1, std::ref(semaphore1), std::ref(semaphore2));std::thread t2(task2, std::ref(semaphore1), std::ref(semaphore2));std::thread t3(task3, std::ref(semaphore2));t1.join();t2.join();t3.join();return 0;
}

信号量怎么实现?

C++11

使用互斥锁和条件变量模拟信号量。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>class Semaphore {
public:Semaphore(int count) : _count(count) {}void acquire() {std::unique_lock<std::mutex> lock(_mutex);while (_count == 0) {_cv.wait(lock);}--_count;}void release() {std::lock_guard<std::mutex> lock(_mutex);++_count;_cv.notify_one();}private:int _count;std::mutex _mutex;std::condition_variable _cv;
};Semaphore taskSemaphore(4); // 最大并发数为4void processTask(int taskID) {taskSemaphore.acquire();std::cout << "Task " << taskID << " started." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(10));std::cout << "Task " << taskID << " finished." << std::endl;taskSemaphore.release();
}int main() {std::vector<std::thread> threads;const int numTasks = 10;for (int i = 1; i <= numTasks; ++i) {threads.emplace_back(processTask, i);}for (auto& thread : threads) {thread.join();}return 0;
}

C++20

使用std::counting_semaphore

#include <iostream>
#include <thread>
#include <semaphore>
#include <vector>// 假设我们有一个最大并发数为4的任务队列
std::counting_semaphore<4> taskSemaphore(4);void processTask(int taskID) {// 请求一个任务许可taskSemaphore.acquire();std::cout << "Task " << taskID << " started." << std::endl;// 这里模拟任务处理时间std::this_thread::sleep_for(std::chrono::milliseconds(10000));std::cout << "Task " << taskID << " finished." << std::endl;// 任务处理完释放许可taskSemaphore.release();
}int main() {std::vector<std::thread> threads;const int numTasks = 10;for (int i = 1; i <= numTasks; ++i) {threads.emplace_back(processTask, i);}for (auto& thread : threads) {thread.join();}return 0;
}

经典生产者消费者问题

#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <chrono>
#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 1) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mutex_);++count_;condition_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mutex_);while (count_ <= 0) {condition_.wait(lock);}--count_;}private:std::mutex mutex_;std::condition_variable condition_;int count_;
};const int BUFFER_SIZE = 10;
std::queue<int> buffer;
std::mutex mutex_; // 互斥锁,用于保护共享数据
Semaphore empty(BUFFER_SIZE), full(0);void producer(int producerId) {for (int i = 0; i < 100; ++i) {empty.wait(); // 等待缓冲区有空位std::unique_lock<std::mutex> lock(mutex_);buffer.push(i);std::cout << "Producer " << producerId << " produced: " << i << std::endl;lock.unlock();full.notify(); // 通知消费者有新数据}
}void consumer(int consumerId) {for (int i = 0; i < 100; ++i) {full.wait(); // 等待缓冲区有数据std::unique_lock<std::mutex> lock(mutex_);int data = buffer.front();buffer.pop();std::cout << "Consumer " << consumerId << " consumed: " << data << std::endl;lock.unlock();empty.notify(); // 通知生产者有空位}
}int main() {std::vector<std::thread> producers, consumers;// 创建3个生产者线程for (int i = 0; i < 3; ++i) {producers.push_back(std::thread(producer, i));}// 创建3个消费者线程for (int i = 0; i < 3; ++i) {consumers.push_back(std::thread(consumer, i));}// 等待所有生产者线程完成for (auto& producer : producers) {producer.join();}// 等待所有消费者线程完成for (auto& consumer : consumers) {consumer.join();}return 0;
}

这篇关于信号量Semaphore的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/919080

相关文章

Linux多线程——POSIX信号量与环形队列版本之生产消费模型

文章目录 POSIX信号量POSIX的操作初始化销毁等待信号量(申请资源)发布信号量(放下资源) 环形队列之生产消费模型 POSIX信号量 POSIX信号量和System V信号量是不同的标准 但是实现的功能是一样的,都是为了解决同步的问题 我们说信号量指的就是资源的数量 在生产者与消费者模型里面,生产者与消费者所认为的资源是不同的 生产者认为空间是资源,因为每次都要

信号与信号量的区别[转]

信号量(Semaphore),有时被称为信号灯,是在多环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Se

使用信号量实现一个限流器:C++实战指南

使用信号量实现一个限流器:C++实战指南 在现代软件开发中,限流器(Rate Limiter)是一种常用的技术,用于控制系统的请求速率,防止系统过载。信号量(Semaphore)是一种强大的同步原语,可以用于实现限流器。本文将详细介绍如何在C++中使用信号量实现一个限流器,并提供完整的代码示例和详细的解释。 什么是限流器? 限流器是一种控制系统请求速率的机制,确保在单位时间内处理的请求数量不

java 多线程 CountDownLatch、CyclicBarrier、Semaphore

在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法。   以下是本文目录大纲:   一.CountDownLatch用法   二.CyclicBarrier用法   三.Semaphore用法   若有不正之处请多多谅解,并欢迎批评指正。

C++ 信号量

信号量: 在生产者消费者模型中,对任务数量的记录就可以使用信号量来做。当信号量的值小于0时,工作进程或者线程就会阻塞,等待物品到来。当生产者生产一个物品,会将信号量值加1操作 sem_post(&sem)。 这是会唤醒在信号量上阻塞的进程或者线程sem_wait(&sem),它们去争抢物品。 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是⼀个非负的整数计数器,它被用来控制对公共资源的访

【嵌入式】内存未对齐导致程序崩溃(铺获信号量SIGBUS,数值7)

背景 嵌入式平台上,和A组配合,需要把A组提供的二进制文件在调用A组提供接口时传入,因为有多个bin文件,自测的时候选择了其中一个,运行正常。递交给qa测试了。然后qa反馈必现崩溃。懵了。复现的时候还用的之前的bin文件,无法复现。最后看信号量数值和打印日志判断是在调用接口的地方,然后对了下长度,发现奇数。而自己用的偶数大小的bin文件。然后修改4字节对齐后正常了。 问题现象 日志打印提示:

【Linux】消息队列信号量

目录 消息队列 原理 接口 指令 信号量 概念 对于信号量理论的理解 信号量的操作  信号量的指令 消息队列 原理 消息队列提供了一个从一个进程向另外一个进程发送一个数据块的方法,每个数据块都有一个类型。对消息队列的的管理也是先描述,再组织! 接口 我们发现,消息队列和共享内存的接口极其相似,消息队列的属性也保存在ipc_perm结构体中,这个结构以中的第一

Java并发编程--深入理解Semaphore

Semaphore简介 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。 Semaphore的用途 Semaphore可以用于做流量控制,特别公用资源有限的应用场景,比如数据库连接。假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发的读取,但是如果读到内存后,还需要存储到数据库中,而数据库

FreeRTOS线程同步1---信号量

目录 二值信号量 二值信号量相关API函数 一般使用方法为 1.创建二值信号量 2.在一个任务中置为二值释放信号 3.在另一个任务中获取信号 计数信号量 计数型信号量相关 API 函数 使用方法 1.创建计数信号量 2.释放计数信号量 3.获得信号量的当前值 4.释放信号量 互斥信号量 互斥信号量常用API函数 使用方法         信号量是一种解决同

java 信号量Semaphore的使用

java 信号量Semaphore的使用 信号量是一种计数器,用来保护一个或者多个共享资源的访问。 信号量的使用: (1)如果一个线程要访问一个共享资源,他必须先获得信号量。如果信号量的内部计数器大于0,信号量将减1,然后允许访问这个共享资源。计数器大于0意味着又可以使用的资源,因此线程讲被允许使用其中一个资源。 (2)如果信号量等于0,信号将将会把线程植入休眠直到计数器大于0.计数器等于