新浪博客

c++多线程锁机制:信号量和counting_semaphore

2024-10-05 18:00阅读:
使用信号量 counting_semaphore实现的互斥锁(mutex)


c++多线程锁机制:信号量和counting_semaphore————————————————————
visual studio 2022,项目
上面右键--属性--常规--c++语言标准-------选择 isoc++20
否则std::counting_semaphore<1>
sem(1) 因为低版本c++ 不支持 c++20特性,就 报错


c++多线程锁机制:信号量和counting_semaphore
————————————————————
#include iostream
#include thread
#include semaphore
#include vector
#include std::counting_semaphore<1> sem(1); //
初始化为1,表示任一时刻只允许一个线程进入临界区


void worker(int id)
{
sem.acquire();
std::cout << ' work id is '<< id << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));


std::cout<< ' work id is ' << id << ' done ' <<std::endl;
sem.release();
}


int main()
{ std::vector threads;


for
(int i = 0; i < 5; ++i)
{ threads.emplace_back(worker, i);
//emplace:“place in position”,强调直接在目标位置构造对象,而非先构造再移动。
//back:表示操作是在容器的尾部进行。
}
for (auto& t :
threads) { t.join(); // 等待所有线程完成,即为保证所有线程执行完毕才可以推出 主线程main } return
0; }


c++多线程锁机制:信号量和counting_semaphore c++多线程锁机制:信号量和counting_semaphore——————————————————————————————
c++多线程锁机制:信号量和counting_semaphore
c++多线程锁机制:信号量和counting_semaphore
1、std::counting_semaphore<1> sem(1);


前面的1 代表 定义了一个信号量 sem,其最大计数为 1,意味着它可以被用来保证在任何时刻,只有一个线程可以通过这个信号量。
后面的1是初始化sem 为1 的意思。
c++多线程锁机制:信号量和counting_semaphore


2、分析各个部分:
std::counting_semaphore<1>:


std::counting_semaphore 是模板类,其模板参数指定了信号量的最大计数。
<1> 表示这个信号量的最大计数为 1,这使得它的行为类似于一个互斥锁(mutex),即一次只允许一个线程持有该信号量。
sem(1):


这是 std::counting_semaphore 的构造函数调用,其中的 1 是构造函数的参数,表示信号量的初始计数。
初始计数也设置为 1,意味着在信号量创建时,它是空闲的,允许第一个请求它的线程成功获得并进入其保护的临界区。
c++多线程锁机制:信号量和counting_semaphorec++多线程锁机制:信号量和counting_semaphore
3、行为和用法
acquire() 方法:


当线程调用 sem.acquire() 时,它会尝试减少信号量的计数。如果计数已经是 0(表示其他线程已经占用了资源),调用线程将会阻塞,直到信号量的计数再次变为正数(即信号量被释放)。
release() 方法:


当线程完成对共享资源的访问后,它应调用 sem.release() 来增加信号量的计数。这可能会唤醒正在等待这个信号量的其他线程。


——————————————————————
c++多线程锁机制:信号量和counting_semaphore c++多线程锁机制:信号量和counting_semaphore
4、threads.emplace_back(worker, i)
emplace:“place in position” ,强调直接在目标位置构造对象,而非先构造再移动。back:表示操作是在容器的尾部进行。
emplace_back 方法 是在threads的末尾 直接构造std::thread对象。


5、比较 emplace_back 和 push_back


对比传统的 push_back 方法,emplace_back 更加高效,
尤其是当构造复杂对象或涉及到移动语义时。
push_back 需要一个已经构造好的对象作为参数,这意味着它通常会先构造一个临时对象,然后将其复制或移动到容器中。


相反,emplace_back 直接在容器的存储空间中构造对象,避免了额外的复制或移动步骤。

我的更多文章

下载客户端阅读体验更佳

APP专享