c++多线程(一)- 互斥量(mutex)

1.lock() / unlock()

   lock()锁定需要保护的代码区域,使之某一时刻只有一个线程访问。unlock()解除对代码区域的锁定,使其它线程可以访问。

   lock()和unlock()必须成对使用。锁定后不解锁,或者重复解锁都会出问题。

//lock()和unlock()要成对使用。
//分析需要保护的代码段
class MsgManage
{
public:
	MsgManage() {}
	~MsgManage() {}
	void InMsg()
	{
		for (int i = 0; i < 10000; i++)
		{			
			cout << "插入元素: " << i << endl;
			myMutex.lock();
			myList.push_back(i);
			myMutex.unlock();
		}
	}


	bool outMsgProc(int &num)
	{
		myMutex.lock();
		if (!myList.empty())
		{
		    num = myList.front();
			myList.pop_front();
			myMutex.unlock();
			return true;
		}
		myMutex.unlock();
		return false;
	}

	void OutMsg()
	{
		for (int i = 0; i < 10000; i++)
		{
			int num;
			
			bool result = outMsgProc(num);
			
			if (result)
			{
				cout << "移除元素: " << num << endl;
			}		
			else
			{
				cout << "消息队列为空" << endl;
			}
		}
	}
private:
	list<int> myList;
	mutex myMutex;
};


int main()
{
	MsgManage manage;
	thread outMsg(&MsgManage::OutMsg, &manage);
    thread inMsg(&MsgManage::InMsg, &manage);
	inMsg.join();
    outMsg.join();

	return 0;
}

2.lock_guard模板

    lock()和unlock()必须成对使用。但是程序员很容易lock()后忘记调用unlock(),导致代码段长时间锁定。为了避免这个问题,lock_guard模板是一个好的选择。lock_guard会在构造函数里调用lock(),在析构函数里调用unlock(),程序员再也不用担心资源释放的问题了。

    使用lock_guard需要注意的是,由于它在析构时才解锁,所以程序员需要明确锁定的代码区域,避免锁定过多影响效率。

bool outMsgProc(int &num)
{
	lock_guard<mutex> guard(myMutex);
	if (!myList.empty())
	{
		num = myList.front();
		myList.pop_front();
		return true;
	}
	return false;
}

3.std::lock()

   lock()可以同时给多个互斥量加锁。如果有互斥量加锁失败,则会释放掉加锁成功的互斥量,从而避免死锁。使用该lock()时,不要忘记使用unlock()解除锁定。

bool outMsgProc(int &num)
{
	lock(myMutex1, myMutex2); //同时对两个互斥量加锁
	if (!myList.empty())
	{
		num = myList.front();
		myList.pop_front();
		myMutex1.unlock();
		myMutex2.unlock();
		return true;
	}
	myMutex1.unlock();
	myMutex2.unlock();
	return false;
}

    可以混合使用lock_guard()和lock(),避免了忘记unlock()引发的问题。

bool outMsgProc(int &num)
{
	lock(myMutex1, myMutex2); //同时对两个互斥量加锁
	lock_guard<mutex> guard1(myMutex1, adopt_lock); //adopt_lock表示互斥量已经锁定,解锁交给lock_guard对象
	lock_guard<mutex> guard2(myMutex2, adopt_lock);
	if (!myList.empty())
	{
		num = myList.front();
		myList.pop_front();
		return true;
	}
	return false;
}

   

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/86615661
今日推荐