并发程序设计

1. 按序打印


  题目来源于力扣 1114。测序程序:

void print1() { cout << "first"; }
void print2() { cout << "second"; }
void print3() { cout << "third"; }
int main() {
	Foo fo;
	thread th1(&Foo::first, &fo, print1);
	thread th2(&Foo::second, &fo, print2);
	thread th3(&Foo::third, &fo, print3);
	th1.join();
	th2.join();
	th3.join();
}

方法 1 互斥锁:设置两把锁并锁住,用于阻止线程 2 和线程 3 运行。线程 1 运行完打开线程 2 的锁,线程 2 运行完打开线程 3 的锁。

class Foo {
	mutex mtx_1, mtx_2;
	unique_lock<mutex> lock_1, lock_2;
public:
	Foo() : lock_1(mtx_1, try_to_lock), lock_2(mtx_2, try_to_lock) {} // second和third线程被锁住。
	void first(function<void()> printFirst) {
		printFirst();
		lock_1.unlock(); // second线程解锁。
	}
	void second(function<void()> printSecond) {
		lock_guard<mutex> guard(mtx_1); // 获取second线程的锁mtx_1。
		printSecond();
		lock_2.unlock();
	}
	void third(function<void()> printThird) {
		lock_guard<mutex> guard(mtx_2);
		printThird();
	}
};

2. 交替打印


  题目来源于力扣 1115。测序程序:

#include<iostream>
#include<thread>
using namespace std;
void print1() { cout << "Foo" << endl; }
void print2() { cout << "Bar" << endl; }
int main() {
	FooBar fo(10);
	thread th1(&FooBar::foo, &fo, print1);
	thread th2(&FooBar::bar, &fo, print2);
	th1.join();
	th2.join();
}

方法 1 循环等待:

class FooBar {
public:
	FooBar(int x) :n(x), index(1) {}
	void foo(function<void()> printFoo) {
		for (int i = 0; i < n; i++) {
			while (index != 1)
				this_thread::yield();
			printFoo();
			index = 2;
		}
	}
	void bar(function<void()> printBar) {
		for (int i = 0; i < n; i++) {
			while (index != 2)
				this_thread::yield();
			printBar();
			index = 1;
		}
	}
private:
	int n, index;
};

  简单来说就是在线程中使用 while。循环等待,第7行和第15行可以是空循环体。这两行的作用是主动让出CPU时间片,避免不间断地判断循环条件。
  疑问:这种方法能保证 index 一致性吗。测试程序创建线程时 fo 为什么要加 &。

方法 2 条件变量:

class FooBar {
public:
	FooBar(int x) :n(x), index(1) {}
	void foo(function<void()> printFoo) {
		for (int i = 0; i < n; i++) {
			unique_lock<mutex> lock(mt); //为了防止竞争,条件变量总是和一个互斥锁结合使用。
			cv.wait(lock, [this]() { return index == 1; }); //阻塞该线程直到满足条件。
			printFoo();
			index = 2;
			cv.notify_one(); //发信号并随机唤醒一个等待的线程。
		}
	}
	void bar(function<void()> printBar) {
		for (int i = 0; i < n; i++) {
			unique_lock<mutex> lock(mt);
			cv.wait(lock, [this]() { return index == 2; });
			printBar();
			index = 1;
			cv.notify_one();
		}
	}
private:
	int n, index;
	condition_variable cv;
	mutex mt;
};

3. 参考


  1. 力扣多线程题库
  2. 按序打印
  3. 循环等待
  4. 条件变量实现交替打印
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值