unique_lock使用示例、源码分析

一、概要

unique_lock实现了lock_guard类似的功能,但unique_lock保证了只有一个unique_lock拥有mutex,同时提供了转移拥有权的接口。

二、代码示例

#pragma once
#include <mutex>
#include <thread>
#include <iostream>
using namespace std;
class UniqueLockTest
{
    
    
private:
	mutex _mutex;
	int count;
public:
	void process()
	{
    
    
		for (int i = 0; i < 10000; i++)
		{
    
    
			unique_lock<mutex> lock1(_mutex);
			//lock1.lock(); //unique_lock构造的时候已经lock了,再lock就死锁了
			count++;
		}
	}
	void doTest()
	{
    
    
		thread t1([this]() {
    
    this->process(); });
		thread t2([this]() {
    
    this->process(); });
		t1.join();
		t2.join();
		unique_lock<mutex> lock1(_mutex);
		count++;
		//unique_lock<mutex> lock2 = lock1; //编译过不了,赋值操作符被删除,避免mutex被两个对象引用
		//unique_lock<mutex> lock2(lock1); //编译过不了,删除了拷贝构造函数
		unique_lock<mutex> lock2;
		lock2.swap(lock1); //交换控制权
		//lock2.lock(); //lock1原本是锁着的,交还给lock2还是锁着的,再锁的话,就死锁了
		count++;

		unique_lock<mutex> lock3(std::move(lock2)); //转移lock2的控制权给lock3
		//lock3.lock(); //lock2原本是锁着的,移动构造给lock3后还是锁着的,再锁的话,就死锁了
		count++;

		unique_lock<mutex> lock4;
		lock4 = std::move(lock3); //右值引用
		//lock4.lock(); //lock3原本是锁着的,移动赋值给lock4后还是锁着的,再锁的话,就死锁了
		count++;

		cout << count << endl;
	}
};

三、unique_lock主要源码

template<class _Mutex> class unique_lock
{
    
    
public:
	typedef unique_lock<_Mutex> _Myt;
	typedef _Mutex mutex_type;

	// CONSTRUCT, ASSIGN, AND DESTROY
	unique_lock() _NOEXCEPT
		: _Pmtx(0), _Owns(false)
	{
    
    	// default construct
	}

	explicit unique_lock(_Mutex& _Mtx)
		: _Pmtx(&_Mtx), _Owns(false)
	{
    
    	// construct and lock
		_Pmtx->lock();
		_Owns = true;
	}

	unique_lock(unique_lock&& _Other) _NOEXCEPT //定义了移动构造函数,用来转移控制权
		: _Pmtx(_Other._Pmtx), _Owns(_Other._Owns)
	{
    
    	// destructive copy
		_Other._Pmtx = 0;
		_Other._Owns = false;
	}

	unique_lock& operator=(unique_lock&& _Other) //
	{
    
    	// destructive copy
		if (this != &_Other)
		{
    
    	// different, move contents
			if (_Owns)
				_Pmtx->unlock();
			_Pmtx = _Other._Pmtx;
			_Owns = _Other._Owns;
			_Other._Pmtx = 0;
			_Other._Owns = false;
		}
		return (*this);
	}

	~unique_lock() _NOEXCEPT
	{
    
    	// clean up
		if (_Owns)
			_Pmtx->unlock();
	}

	unique_lock(const unique_lock&) = delete; //删除了拷贝构造函数
	unique_lock& operator=(const unique_lock&) = delete; //删除了赋值

	// LOCK AND UNLOCK
	void lock()
	{
    
    	// lock the mutex
		_Validate();
		_Pmtx->lock();
		_Owns = true;
	}

	bool try_lock()
	{
    
    	// try to lock the mutex
		_Validate();
		_Owns = _Pmtx->try_lock();
		return (_Owns);
	}

	void unlock()
	{
    
    	// try to unlock the mutex
		if (!_Pmtx || !_Owns)
			_THROW_NCEE(system_error,
				_STD make_error_code(errc::operation_not_permitted));

		_Pmtx->unlock();
		_Owns = false;
	}

	// MUTATE
	void swap(unique_lock& _Other) _NOEXCEPT
	{
    
    	// swap with _Other
		_STD swap(_Pmtx, _Other._Pmtx);
		_STD swap(_Owns, _Other._Owns);
	}

	_Mutex *release() _NOEXCEPT
	{
    
    	// disconnect
		_Mutex *_Res = _Pmtx;
		_Pmtx = 0;
		_Owns = false;
		return (_Res);
	}
private:
	_Mutex *_Pmtx;
	bool _Owns;

	void _Validate() const
	{
    
    	// check if the mutex can be locked
		if (!_Pmtx)
			_THROW_NCEE(system_error,
				_STD make_error_code(errc::operation_not_permitted));

		if (_Owns)
			_THROW_NCEE(system_error,
				_STD make_error_code(errc::resource_deadlock_would_occur));
	}
};

四、unique_lock源码分析

禁用了普通的赋值和拷贝构造,来保证只要一个unique_lock拥有mutex。
提供了移动赋值和移动拷贝构造以及swap方法来转移拥有权。

猜你喜欢

转载自blog.csdn.net/gamekit/article/details/107420581