线程数量并不是越多越好,有些情况下,需要限制线程的数量。

这里需要用到互斥锁mutex,条件变量condition_variable,通用互斥锁包装器unique_lock

std::unique_lock也可以提供自动加锁、解锁功能,比std::lock_guard更加灵活。

类 unique_lock 是通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用。

unique_lock比lock_guard使用更加灵活,功能更加强大。

使用unique_lock需要付出更多的时间、性能成本。

 

全局的互斥锁m,用于锁定“process_number”,搭配unique_lock使用。

 

 

当一个线程执行完了之后就让process_number减1,然后唤醒所有等待线程

条件变量(condition variable),c++11中提供了#include <condition_variable>头文件,其中的std::condition_variable可以和std::mutex结合一起使用,其中有两个重要的接口,notify_one()和wait(),

wait()可以让当前线程陷入休眠状态。(也就是程序停止在wait处不再往下执行)

notify_all()就是唤醒处于wait中的所有线程(可能当时有很多线程都处于wait状态)。
————————————————
版权声明:本文为CSDN博主「yxpandjay」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

 

这里再condition.wait(lck)外面还要套一层循环while(process_number>5)的意思就是,因为同时唤醒了很多线程,

while (process_number > 5) {
    condition.wait(lck);
}

如果没有这一层循环可能会有两个或者多个线程反应快同时启动,那就不可能限制住线程数量了,

因此需要在每个线程重启启动的时候,都去看看循环中的条件是否满足,再去执行,如果有其他线程抢先了,就继续wait

 

完整代码:

#include <iostream>  
#include <thread>
#include <mutex>
#include <stdio.h>
#include<vector>
using namespace std;
mutex m;
condition_variable condition;
int process_number;

void t1(int id) {
	if (process_number > 5) {
		unique_lock<mutex> lck(m);
		printf("id: %d, process_number: %d, waiting thread ID %d\n", id, process_number, std::this_thread::get_id());
		while (process_number > 5) {
			condition.wait(lck);
		}
	}
	process_number += 1;

	printf("id: %d, process_number: %d, doing thread ID %d\n", id, process_number, std::this_thread::get_id());
	double sum = 0;
	for (double i = 0; i < 1e10; i++) {
		sum += i;
	}
	printf("id: %d, process_number: %d, doing thread ID %d get sum = %f\n", id, process_number, std::this_thread::get_id(),sum);

	process_number -= 1;
	condition.notify_all();
}

int main() {
	process_number = 0;
	vector<thread> th_set;
	for (int i = 0; i < 20; i++) {
		//thread th1(t1,i);
		//th1.join();
		th_set.push_back(thread(t1, i));
	}
	for (auto &th : th_set) {
		th.join();
	}
	system("pause");
	return 0;
}

java定义限制数量的队列_java定义限制数量的队列

一开始有6个线程开始工作,其他线程等待。

java定义限制数量的队列_#include_02

当id=3的线程执行结束了之后,id=9的线程开始执行。

 

 

这里要注意的是,再for循环中开启线程不可以这样写:

for (int i = 0; i < 20; i++) {
    thread th1(t1,i);
    th1.join();
}

因为join是子线程执行完后主线程回收子线程资源,本来没啥毛病,但是用在for循环中就会导致主线程在for循环里面等着线程执行完了回收资源,那就等于顺序执行,同一时间只执行一个线程(自行测试)

那么解决方法就是先用一个vector把线程先装起来,等for循环结束以后再统一回收资源。

vector<thread> th_set;
for(int i = 0; i < 20; i++) {
    th_set.push_back(thread(t1, i));
}