【面試練習題】C++ 使用多線程實現交替打印兩個數組 + PV操作

互斥鎖的版本:

#include <string>
#include <thread>
#include <mutex>
#include <iostream>
using namespace std;

std::mutex data_mutex;
int flag = 0;

void printA(int* a, int size) {
	for (int i = 0; i < size; ) {
		data_mutex.lock();
		if (flag == 0) {
			cout << a[i] << endl;
			flag = 1;
			++i;
		}
		data_mutex.unlock();
	}
}

void printB(char* b, int size) {
	for (int i = 0; i < size; ) {
		data_mutex.lock();
		if (flag == 1) {
			cout << b[i] << endl;
			flag = 0;
			++i;
		}
		data_mutex.unlock();
	}
}

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	char b[4] = { 'a', 'b', 'c', 'd' };
	std::thread tA(&printA, a, 4);
	std::thread tB(&printB, b, 4);
	tA.join();
	tB.join();

	return 0;
}

使用互斥鎖+條件變量的版本:

#include <string>
#include <thread>
#include <mutex>
#include <iostream>
using namespace std;

std::mutex data_mutex;
std::condition_variable data_var;
int flag = 0;

void printA(int* a, int size) {
	for (int i = 0; i < size; i++) {
		
		std::unique_lock<std::mutex> lck(data_mutex);
		data_var.wait(lck, [] {return flag == 0; });
		
		cout << a[i] << endl;
		flag = 1;
		
		data_var.notify_all();
		
	}
}

void printB(char* b, int size) {
	for (int i = 0; i < size; ++i) {
		std::unique_lock<std::mutex> lck(data_mutex);
		data_var.wait(lck, [] {return flag == 1; });
		
		cout << b[i] << endl;
		flag = 0;
		
		data_var.notify_all();
	}
}

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	char b[4] = { 'a', 'b', 'c', 'd' };
	std::thread tA(&printA, a, 4);
	std::thread tB(&printB, b, 4);
	tA.join();
	tB.join();

	return 0;
}

PV操作

#include <thread>
#include <mutex>
#include <iostream>
#include <vector>

using namespace std;
const int PRONUM = 10; // 生產者總個數
const int CONSUNUM = 5; // 消費者總個數
const int SUM = 30; // 需要的商品總個數
const int CAP = 20; // 緩衝區長度
vector<int> storage(CAP); // 緩衝區
int cnt = 0; // 倉庫內貨物計數器,判斷是全滿還是全空
mutex mutex_storage;// 保護緩衝區的鎖
condition_variable con_emp;
condition_variable con_full;
static int has_consumed = 0; // 總共消費的
static int has_produced = 0; // 總共生產的

class Pointer {
private:
	int p;
public:
	Pointer() : p(0){}
	int& operator++() {
		p++;
		if (p == CAP) {
			p = 0;
		}
		return p;
	}
	int& operator++(int) {
		return ++(*this);
	}
	int& operator*() {
		return p;
	}
};

Pointer p_em; // 指向第一個空的位置
Pointer p_full; // 指向第一個滿的位置

// 生產者線程
void produce() {
	do{
		unique_lock<mutex> lck(mutex_storage);
		con_emp.wait(lck, []() {return cnt != CAP; });
		storage[*p_em] = has_produced;
		cnt++;
		cout << this_thread::get_id() << "生產了" << storage[*p_em] << "號, 目前有:" << cnt << "個" << endl;
		this_thread::sleep_for(std::chrono::milliseconds(100));
		p_em++;
		has_produced++;
		con_full.notify_one();
	} while (has_produced <= SUM);
}

void consume() {
	do {
		unique_lock<mutex> lck(mutex_storage);
		con_full.wait(lck, []() {return cnt != 0; });
		cnt--;
		cout << this_thread::get_id() << "消費了" << storage[*p_full] << "號, 目前有:" << cnt << "個" << endl;
		this_thread::sleep_for(std::chrono::milliseconds(500));
		p_full++;
		has_consumed++;
		con_emp.notify_one();
	} while (has_consumed <= SUM);
}

int main()
{
	vector<thread> vec_p;
	vector<thread> vec_c;
	for (int i = 0; i < PRONUM; ++i) {
		vec_p.push_back(thread(produce));
	}
	for (int i = 0; i < CONSUNUM; ++i) {
		vec_c.push_back(thread(consume));
	}
	for (int i = 0; i < PRONUM; ++i) {
		vec_p[i].join();
	}
	for (int i = 0; i < CONSUNUM; ++i) {
		vec_c[i].join();
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章