C++多线程编程(一)

转自:http://www.bogotobogo.com/cplusplus/C11/6_C11_Thread_with_Move_Semantics.php

Thread with Move Semantics

#include<thread>
#include<vector>
#include<algorithm>
#include<cassert>
#include<iostream>
using namespace std;


void task(int i) {
	cout << "workers " << i << endl;
}


int main() {

	vector<thread> workers;

	for (int i = 0; i < 5; i++)
	{
	/*	auto t = thread([i]() {

			cout << "thread function" <<i<< endl;
		});*/
		auto t = thread(&task, i);
		auto t1 = thread(&task, ref(i));//It seems to be working fine, but in general, tossing reference (aliases) around is not a good idea.
		//Because it means multiple threads are holding a reference which is pointing to the same object.

		workers.push_back(std::move(t1));
	}
	cout << "main thread" << endl;

	/*
	each element from the collection will be passed to the function as a parameter 
	and function will be executed the number of times elements present in a collection.
	*/
	std::for_each(workers.begin(), workers.end(), [](std::thread &t) {
		assert(t.joinable());
		t.join();
	});

	getchar();
	return 0;

Sharing resources

//http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
#include<iostream>
#include<thread>
#include<mutex>
#include<string>
using namespace std;

/*

This seemingly innocent short code has already an issue of
race condition for a resource, cout.:

*/

mutex mu;
void share_function(string s,int id) {
	mu.lock();
	cout << s<< " "<<id<<endl;
	mu.unlock();
}

void thread_function() {
	for (int i = 0; i < 5; i++)
	{
		share_function("thread function", i);

	}
}
int main() {
	for (int i = 0; i < 5; i++)
	{
		share_function("main function", i);
	}

	thread t(&thread_function);
	
	
	//t.join();
	getchar();
	return 0;

}

Mutexes

lock()、unlock()、lock_guard()

In C++, we create a mutex by constructing an instance of std::mutex, lock it with a call to the member function lock(), and unlock it with a call to the member function unlock(). However, it is not a good practice to call the member functions directly, because this means that we have to remember to call unlock() on every code path out of a function, including those due to exceptions.

In other words, if we have an exception in the code after the lock() but before the unlock(), then we'll have a problem. The resources are in locked state!

So, the Standard C++ Library provides the std::lock_guard class template, which implements that RAII idiom for a mutex. It locks the supplied mutex on construction and unlocks it on destruction, thus ensuring a locked mutex is always correctly unlocked.

The example below shows how to protect a list that can be accessed by multiple threads using a std::mutex, along with std::lock_guard. Both of these are declared in the <mutex> header.

std::lock_guard 与mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁。

#include<iostream>
#include<thread>
#include<mutex>
#include<string>
#include<list>

using namespace std;

list<int> MyList;

mutex myMutex;

const int MAX = 100;
void addToList(int interval,int id) {
	
	//对这个函数的访问是互斥的
	lock_guard<mutex> guard(myMutex);
	for (int i = 0; i < MAX; i++){
		if (i%interval == 0)
			MyList.push_back(i);
	}
	cout << "thread " << id << "runing..........." << endl;
}
void PrintList() {

    //对这个函数的访问是互斥的
	lock_guard<mutex> guard(myMutex);
	for (auto it = MyList.begin(); it != MyList.end(); it++) {
		cout << *it << ","<<endl;
	}
}

int main() {

	thread t1(&addToList, 2,1);
	thread t2(&addToList,3,2);
	thread t3(&PrintList);

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

	getchar();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值