C++11 生产者消费者模型

C++11 生产者消费者模型

线程互斥 lock_guard

使用lock_guard管理互斥锁。在退出作用域后进行析构时就会自动解锁,从而保证了互斥量的正确操作,避免忘记 unlock() 操作而导致线程死锁

std::lock_guard<std::mutex> lck(mtx);
  • 线程lock_guard生命周期内自动加锁和解锁,其中加锁和解锁分别在构造函数和析构函数中完成
  • 不能对lock_guard进行拷贝或赋值。lock_guard不能用于参数传递或返回值中。

线程互斥unique_lock

unique_lock有着 lock_guard一样的功能,都是比 lock_guard更灵活,可以指定一些参数和方法。但是比 lock_guard更占用资源。

  • unique_lock提供了右值引用参数的拷贝构造与赋值,可以用于用于参数传递或返回值中。
  • unique_lock可以取代lock_guard
std::unique_lock<std::mutex> lck(mtx);

线程同步 条件变量 condition_variable

与互斥锁(unique_lock)一起使用,实现线程同步

std::condition_variable cv;
cv.wait(lck); //使线程进入等待状态 并且释放互斥锁
cv.notify_all();//通知其他线程 其他线程得到该通知,就会从等待状态变为阻塞状态,等着拿到锁

生产者消费者代码示例

#include
#include
#include
#include
#include

using namespace std;

std::mutex mtx;
std::condition_variable cv;

//C++的stl容器都不是线程安全的 需要自己封装出线程安全的类
class Queue {
public:
	void put(int val) {
		//将互斥锁用unique_lock封装 更安全
		//如果此线程没拿到锁 就会阻塞在这 如果拿到了锁 unique_lock就会在出作用域时自动释放锁
		unique_lock<std::mutex> lck(mtx); 
		//que中还有商品 就先让消费者消费 消费完了 再继续生产

		while (!que.empty()) {
			cv.wait(lck); //使生产者进入等待状态 并且释放互斥锁
		}
		
		que.push(val);
		
		//通知消费者可以消费了,消费者得到该通知,就会从等待状态变为阻塞状态,拿到锁后就会执行消费
		cv.notify_all();
		cout << "生产者生产物品:" << val << endl;
	}
	int get() {
		unique_lock<std::mutex> lck(mtx); //将互斥锁用unique_lock封装 更安全
		//que中没有商品 就先让生产者生产
		while (que.empty()) {
			cv.wait(lck); //使消费者进入等待状态 并且释放互斥锁
		}
		
		int val = que.front();
		que.pop();
		cv.notify_all();//消费了 通知生产者生产
		cout << "消费者消费物品:" << val << endl;
		return val;
	}
private:
	queue<int>que;
};

//生产者线程
void producer(Queue *que) {
	for (int i = 1; i <= 10; i++) {
		que->put(i);
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}

}
//消费者线程
void consumer(Queue *que) {
	for (int i = 1; i <= 10; i++) {
		que->get();
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
}

int main() {
	Queue que;
	std::thread t1(producer,&que);
	std::thread t2(consumer,&que);

	t1.join();
	t2.join();

	return 0;
}

你可能感兴趣的:(C++,c++,后端)