C++多线程实例

文章详细介绍了C++中实现多线程的几种方法,包括使用`once_flag`确保初始化的原子性,利用互斥体和锁避免数据竞争,以及如何通过条件变量避免死锁。此外,还探讨了异步编程和`future`在处理并发任务中的应用,并展示了C++17的并行算法在排序操作上的性能比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程精讲
https://paul.pub/cpp-concurrency/

  1. 初始化一次
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

void init()
{
	cout << "Initialing..." << endl;
}

void worker(once_flag *flag)
{
	call_once(*flag, init);
}

int main()
{
	once_flag flag;

	thread t1(worker, &flag);
	thread t2(worker, &flag);
	thread t3(worker, &flag);

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

	return 0;
}
  1. 互斥体与锁
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

using namespace std;

static const int MAX = 10e8;
static double sum = 0;

static mutex exclusive;

void concurrent_worker(int min, int max)
{
	double dTmp = 0;
	for (int i = min; i <= max; ++i)
	{
		dTmp += sqrt(i);
	}

	exclusive.lock();
	sum += dTmp;
	exclusive.unlock();
}

void concurrent_task(int min, int max)
{
	auto start_time = chrono::steady_clock::now();
	unsigned concurrent_count = thread::hardware_concurrency();
	cout << "hardware_concurrency:" << concurrent_count << endl;
	vector<thread> threads;
	min = 0;
	sum = 0;
	for (int t = 0; t < concurrent_count; ++t)
	{
		int range = max / concurrent_count * (t + 1);
		threads.push_back(thread(concurrent_worker, min, range));
		min = range + 1;
	}

	for (int i = 0; i < threads.size(); ++i)
	{
		threads[i].join();
	}

	auto end_time = chrono::steady_clock::now();
	auto ms = chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();
	cout << "Concurrent task finish, " << ms << "ms consumed, Result: " << sum << endl;

}

int main()
{
	
	concurrent_task(0, 9999999999999999);
	return 0;
}
  1. 避免死锁
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <string>

using namespace std;

class Account
{

public:
	Account(string name, double money) : m_name(name), m_money(money) {};

public:
	void changeMoney(double amount)
	{
		m_money += amount;
	}

	string getName()
	{
		return m_name;
	}

	double getMoney()
	{
		return m_money;
	}

	mutex* getLock()
	{
		return &m_mtx;
	}

private:
	string m_name;
	double m_money;
	mutex m_mtx;
};

class Bank
{
public:
	void addAccount(Account *account)
	{
		m_Accounts.insert(account);
	}

	bool transferMoney(Account* accountA, Account* accountB, double amount)
	{
		lock(*accountA->getLock(), *accountB->getLock());

		lock_guard<mutex> guardA(*accountA->getLock(), adopt_lock);
		lock_guard<mutex> guardB(*accountB->getLock(), adopt_lock);

		if (amount > accountA->getMoney())
		{
			return false;
		}

		accountA->changeMoney(-amount);
		accountB->changeMoney(+amount);
		return true;
	}

	double totalMoney() const
	{
		double sum = 0;
		for (auto a : m_Accounts)
		{
			sum += a->getMoney();
		}
		return sum;
	}


private:
	set<Account*> m_Accounts;
};

void randomTransfer(Bank* bank, Account* accountA, Account* accountB)
{
	static mutex s_mtx;
	while (true)
	{
		double randomMoney = ((double)rand() / RAND_MAX) * 100;
		if (bank->transferMoney(accountA, accountB, randomMoney))
		{
			lock_guard<mutex> lock(s_mtx);
			std::cout << "Transfer" << randomMoney << "from" 
				<< accountB->getName()
				<< "to" << accountB->getName()
				<< ",Bank totalMoney:" << bank->totalMoney() << endl;
			
		}
		else
		{
			lock_guard<mutex> lock(s_mtx);
			cout << "Transfer failed, "
				<< accountA->getName() << " has only $" << accountA->getMoney() << ", but "
				<< randomMoney << " required" << endl;
		}
	}
}

int main()
{
	Account a("Paul", 100.0);
	Account b("Moiral", 100.0);

	Bank bank;
	bank.addAccount(&a);
	bank.addAccount(&b);

	thread t1(randomTransfer, &bank, &a, &b);
	thread t2(randomTransfer, &bank, &b, &a);

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


	return 0;
}

4.条件变量优化死锁

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

using namespace std;

class Account
{

public:
	Account(string name, double money) : m_name(name), m_money(money) {};

public:
	void changeMoney(double amount)
	{
		unique_lock<mutex> lock(m_mtx);
		m_condition.wait(lock, [this, amount]()
		{
			return m_money + amount > 0;
		});
		m_money += amount;
		m_condition.notify_all();
	}

	string getName()
	{
		return m_name;
	}

	double getMoney()
	{
		return m_money;
	}

	mutex* getLock()
	{
		return &m_mtx;
	}

private:
	string m_name;
	double m_money;
	mutex m_mtx;
	condition_variable m_condition;
};

class Bank
{
public:
	void addAccount(Account *account)
	{
		m_Accounts.insert(account);
	}

	bool transferMoney(Account* accountA, Account* accountB, double amount)
	{
		accountA->changeMoney(-amount);
		accountB->changeMoney(+amount);
		return true;
	}

	double totalMoney() const
	{
		double sum = 0;
		for (auto a : m_Accounts)
		{
			sum += a->getMoney();
		}
		return sum;
	}


private:
	set<Account*> m_Accounts;
};

void randomTransfer(Bank* bank, Account* accountA, Account* accountB)
{
	static mutex s_mtx;
	while (true)
	{
		double randomMoney = ((double)rand() / RAND_MAX) * 100;
		
		{
			lock_guard<mutex> lock(s_mtx);
			std::cout << "Transfer" << randomMoney << "from" 
				<< accountB->getName()
				<< "to" << accountB->getName()
				<< ",Bank totalMoney:" << bank->totalMoney() << endl;
			
		}
		bank->transferMoney(accountA, accountB, randomMoney);
	}
}

int main()
{
	Account a("Paul", 100.0);
	Account b("Moiral", 100.0);

	Bank bank;
	bank.addAccount(&a);
	bank.addAccount(&b);

	thread t1(randomTransfer, &bank, &a, &b);
	thread t2(randomTransfer, &bank, &b, &a);

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


	return 0;
}

5.异步方式执行多线程

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <string>
#include <future>

using namespace std;

static const int MAX = 10e8;
static double sum = 0;

void worker(int min, int max)
{
	cout << "work_thread_id" << this_thread::get_id() << endl;
	for (int i = min; i <= MAX; ++i)
	{
		sum += sqrt(i);
	}
}

int main()
{
	sum = 0;
	cout << "main_thread_id" << this_thread::get_id() << endl;
	auto f1 = async(launch::async, worker, 0, MAX);
	cout << "Async task triggered" << endl;
	f1.wait();
	cout << "Async task finish, result: " << sum << endl;


	return 0;
}
  1. 对类中函数执行异步线程操作
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <string>
#include <future>

using namespace std;

class Worker
{
public:
	Worker(int min, int max) : m_min(min), m_max(max){}
	double work()
	{
		m_result = 0;
		for (int i = m_min; i <= m_max; ++i)
		{
			m_result += sqrt(i);
		}
		return m_result;
	}

	double getResult()
	{
		return m_result;
	}


private:
	int m_min;
	int m_max;
	double m_result;
};


int main()
{
	Worker w(0, 9999999999999999);
	cout << "Task in class triggered" << endl;
	auto f3 = async(&Worker::work, &w);
	f3.wait();
	cout << "Task in class finish, result: " << w.getResult() << endl;
	return 0;
}
  1. packaged_task获取异步操作结果的值
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <string>
#include <future>

using namespace std;

double concurrent_worker(int min, int max)
{
	double sum = 0;
	for (int i = min; i < max; ++i)
	{
		sum += sqrt(i);
	}

	return sum;
}

double concurrent_task(int min, int max)
{
	vector<future<double>> results;

	unsigned concurrent_count = thread::hardware_concurrency();
	min = 0;
	for (int i = 0; i < concurrent_count; ++i)
	{
		packaged_task<double(int, int)> task(concurrent_worker);
		results.push_back(task.get_future());

		int range = max / concurrent_count * (i + 1);
		thread t(std::move(task), min, range);
		t.detach();

		min = range + 1;
	}

	cout << "threads create finish" << endl;
	double sum = 0;
	for (auto& r : results)
	{
		sum += r.get();
	}

	return sum;
}


int main()
{
	auto start_time = chrono::steady_clock::now();
	double r = concurrent_task(0, 9999);
	auto end_time = chrono::steady_clock::now();
	auto ms = chrono::duration_cast<chrono::microseconds>(end_time - start_time).count();
	cout << "Concurrent task finish, " << ms << "ms consumed, Result:" << r << endl;
	return 0;
}
  1. promise与future 任务结束与返回结果分开
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <string>
#include <future>

using namespace std;

double concurrent_worker(int min, int max)
{
	double sum = 0;
	for (int i = min; i < max; ++i)
	{
		sum += sqrt(i);
	}

	return sum;
}

void concurrent_task(int min, int max, promise<double>* result)
{
	vector<future<double>> results;

	unsigned concurrent_count = thread::hardware_concurrency();
	min = 0;
	for (int i = 0; i < concurrent_count; ++i)
	{
		packaged_task<double(int, int)> task(concurrent_worker);
		results.push_back(task.get_future());

		int range = max / concurrent_count * (i + 1);
		thread t(std::move(task), min, range);
		t.detach();

		min = range + 1;
	}

	cout << "threads create finish" << endl;
	double sum = 0;
	for (auto& r : results)
	{
		sum += r.get();
	}

	result->set_value(sum);
	cout << "concurrent_task finish" << endl;
}


int main()
{
	auto start_time = chrono::steady_clock::now();

	promise<double> sum;
	concurrent_task(0, 9999, &sum);

	auto end_time = chrono::steady_clock::now();
	auto ms = chrono::duration_cast<chrono::microseconds>(end_time - start_time).count();
	cout << "Concurrent task finish, " << ms << "ms consumed, Result:" << sum.get_future().get() << endl;
	return 0;
}

8.C++17的并行算法


void generateRandomData(vector<double>& collection, int size) {
	random_device rd;
	mt19937 mt(rd());
	uniform_real_distribution<double> dist(1.0, 100.0);
	for (int i = 0; i < size; i++) {
		collection.push_back(dist(mt));
	}
}

int main() {
	vector<double> collection;
	generateRandomData(collection, 10e6); // ①

	vector<double> copy1(collection); // ②
	vector<double> copy2(collection);
	vector<double> copy3(collection);

	auto time1 = chrono::steady_clock::now(); // ③
	sort(execution::seq, copy1.begin(), copy1.end()); // ④
	auto time2 = chrono::steady_clock::now();
	auto duration = chrono::duration_cast<chrono::milliseconds>(time2 - time1).count();
	cout << "Sequenced sort consuming " << duration << "ms." << endl; // ⑤

	auto time3 = chrono::steady_clock::now();
	sort(execution::par, copy2.begin(), copy2.end()); // ⑥
	auto time4 = chrono::steady_clock::now();
	duration = chrono::duration_cast<chrono::milliseconds>(time4 - time3).count();
	cout << "Parallel sort consuming " << duration << "ms." << endl;

	auto time5 = chrono::steady_clock::now();
	sort(execution::par_unseq, copy2.begin(), copy2.end()); // ⑦
	auto time6 = chrono::steady_clock::now();
	duration = chrono::duration_cast<chrono::milliseconds>(time6 - time5).count();
	cout << "Parallel unsequenced sort consuming " << duration << "ms." << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值