8 - 信号量semaphore

C++20提供了信号量semaphore,可用作其他同步机制(如mutexlatchbarrier)的构件块。

信号量

简介

一个信号量由一个表示很多插槽的计数器组成。计数器在构造函数中初始化。如果获得一个插槽,计数器减少;释放插槽计数器增加。

<semaphore>中定义了两个semaphore类:std::counting_semaphorebinary_semaphore。前者是非负资源计数;后者是只有一个插槽,且该插槽要么是空的要么不是,适合作为互斥的构件块。

常用方法

常用方法如下:

  • acquire():递减计数器。当计数器为零时阻塞,直到计数器再次递增。
  • try_acquire():尝试递减计数器。计数器为零时不会阻塞,如果递减了就返回true,否则返回false
  • try_acquire_for():在给定时间段内尝试递减计数器。
  • try_acquire_until():一直尝试递减计数器,直到到达给定时间。
  • release():计数器增加一个给定的数,并解除在acquire()调用中线程的阻塞。

例子

例如下面代码将允许最多4个线程并行运行:

counting_semaphore semaphore(4);
vector<jthread> threads;

for (int i = 0; i < 10; ++i)
{
	threads.push_back(jthread([&semaphore]
	{
		semaphore.acquire();
		// 最多允许4个线程并行运行
		semaphore.release();
	}));
}

信号量的另一个用例是为线程实现通知机制。例如可在其构造函数中将信号量的计数器初始化为0,任何调用acquire()的线程都会阻塞,直到其他线程对信号量调用release()

参考资料

  • C++20高级编程