小说网站制作,网站制作多少,网站详情页怎么做,网站制作公司权威乐云践新专家头文件在C20中是并发库技术规范#xff08;Technical Specification, TS#xff09;的一部分。信号量是同步原语#xff0c;帮助控制多线程程序中对共享资源的访问。头文件提供了标准C方式来使用信号量。
使用环境
Windows#xff1a;VS中打开项目属性#xff0c;修改C语…头文件在C20中是并发库技术规范Technical Specification, TS的一部分。信号量是同步原语帮助控制多线程程序中对共享资源的访问。头文件提供了标准C方式来使用信号量。
使用环境
WindowsVS中打开项目属性修改C语言标准。
LinuxGCC版本至少应为10.1编译命令中使用-stdc20标志。
简单定义
你可以像这样创建一个信号量对象
std::counting_semaphoresize_t sem(1); // 用初始计数为1初始化一个信号量std::counting_semaphore是一种允许指定数量的线程同时访问资源的信号量。在这个例子中一次只有一个线程可以访问由sem保护的资源。
获取和释放
直接获取
要获取锁定信号量你可以使用acquire方法
sem.acquire();
// 关键段代码
sem.release();acquire方法将信号量计数减一有效地锁定它。release方法增加计数释放信号量。
尝试获取
你也可以使用try_acquire方法来尝试获取信号量而不阻塞
if (sem.try_acquire()) {// 成功获取了信号量// 关键段代码sem.release();
} else {// 信号量未被获取
}带超时的等待
C20还引入了try_acquire_for和try_acquire_until方法以带超时的方式尝试获取信号量。
if (sem.try_acquire_for(std::chrono::seconds(1))) {// 在1秒内成功获取了信号量// 关键段代码sem.release();
} else {// 在1秒内未能获取信号量
}信号量的类型
std::counting_semaphore
计数信号量是一种同步原语允许多个线程在一定限制下访问共享资源。它是互斥锁或二进制信号量的泛化。
你可以用一个初始计数来初始化计数信号量该计数代表可以同时无阻塞访问资源的线程数量。线程可以获取和释放计数信号量的计数相应地增加或减少。如果线程尝试获取的计数超过了可用的数量它将阻塞直到计数变得可用。
// 展示如何使用counting_semaphore
#include iostream
#include semaphore
#include thread
using namespace std;// 用3个计数初始化信号量
counting_semaphore10 semaphore(3);void worker(int id)
{// 获取semaphore.acquire();// 执行一些工作cout Thread id acquired the semaphore. endl;// 释放semaphore.release();cout Thread id released the semaphore. endl;
}int main()
{thread t1(worker, 1);thread t2(worker, 2);thread t3(worker, 3);t1.join();t2.join();t3.join();return 0;
}
输出结果
Thread 2 acquired the semaphore.
Thread 2 released the semaphore.
Thread 1 acquired the semaphore.
Thread 1 released the semaphore.
Thread 3 acquired the semaphore.
Thread 3 released the semaphore.std::binary_semaphore
二进制信号量是一种更简单的信号量版本它只能有两个值0和1。
通常用于两个线程之间的基本互斥或信号传递。可以被视为具有更轻量级接口的互斥锁。类似于mutex。
// 展示二进制信号量的用法
#include iostream
#include semaphore
#include thread
using namespace std;// 用1个计数二进制初始化信号量
binary_semaphore semaphore(1);void worker(int id)
{// 获取信号量semaphore.acquire();cout Thread id acquired the semaphore. endl;// 执行一些工作semaphore.release();// 释放信号量cout Thread id released the semaphore. endl;
}int main()
{thread t1(worker, 1);thread t2(worker, 2);t1.join();t2.join();return 0;
}
输出结果
Thread 1 acquired the semaphore.
Thread 1 released the semaphore.
Thread 2 acquired the semaphore.
Thread 2 released the semaphore.优点
信号量的优势如下
精细控制信号量可以配置为允许特定数量的线程同时访问资源实现资源的精细控制。通用性信号量更加灵活多样可以用来实现其他同步原语。多资源管理计数信号量可以用来管理多个资源实例适用于需要控制对资源池如线程池或连接池访问的场景。阻塞等待信号量中的阻塞和等待机制允许线程等待直到资源再次可用。超时处理在获取信号量时可以指定超时使其更加实用。
例子生产者消费者问题
#include iostream
#include semaphore
#include thread
using namespace std;const int buffer_size 5;// 缓冲区大小
std::binary_semaphore b_mutex(1);
//容量为5 赋初值
std::counting_semaphorebuffer_size b_full(0);
std::counting_semaphorebuffer_size b_empty(5);
void Producer()
{while (true){b_empty.acquire();b_mutex.acquire();std::cout Producer\n;b_mutex.release();b_full.release();//模拟生成过程std::this_thread::sleep_for(std::chrono::seconds(2));}
}
void Consumer()
{while (true){b_full.acquire();b_mutex.acquire();std::cout Consumer\n;b_mutex.release();b_empty.release();//模拟消耗过程std::this_thread::sleep_for(std::chrono::seconds(2));}
}
int main()
{thread t0(Producer);thread t1(Producer);thread t2(Consumer);thread t3(Consumer);t0.join();t1.join();t2.join();t3.join();
}关键组件
b_mutex一个二进制信号量用作互斥锁保证在任何时刻只有一个线程可以操作缓冲区。这是为了防止多个生产者或消费者同时访问缓冲区导致数据不一致的问题。
b_full一个计数信号量表示缓冲区中已填充的项数。初始化为0因为一开始缓冲区是空的。
b_empty另一个计数信号量表示缓冲区中空闲位置的数量。初始化为缓冲区的大小因为起初整个缓冲区都是空的。
生产者Producer
等待一个空闲位置b_empty.acquire();这表示生产者在缓冲区中找到了一个可以放置新生产项的位置。
获取互斥锁b_mutex.acquire();进行生产操作这里通过打印Producer模拟然后释放互斥锁b_mutex.release();这样其他线程生产者或消费者就可以访问缓冲区了。
生产完成后释放一个已满位置的信号b_full.release();告知消费者缓冲区中有项可被消费。模拟生产过程中的延迟std::this_thread::sleep_for(std::chrono::seconds(2));。
消费者Consumer
等待一个已满位置b_full.acquire();这表示消费者在缓冲区中找到了一个可以消费的项。
获取互斥锁b_mutex.acquire();进行消费操作这里通过打印Consumer模拟然后释放互斥锁b_mutex.release();这样其他线程生产者或消费者就可以访问缓冲区了。
消费完成后释放一个空闲位置的信号b_empty.release();告知生产者缓冲区中有位置可用于生产新的项。模拟消费过程中的延迟std::this_thread::sleep_for(std::chrono::seconds(2));。