线程数据共享-解锁与上锁工具探析

需要注意下面方法逐渐增加灵活性,但是增加了时间和空间。

方法一:

1.lock
使用lock函数对互斥元锁定。如果当前锁已经上锁,则会阻塞。
2.try_lock
使用try_lock对互斥元进行上锁,区别于lock,如果当前已上锁,则不会阻塞。
3.try_lock_for和try_lock_until
使用方法如字面意思
4.unlock
对锁进行解锁
缺点:在异常处理时候,没办法自动解锁,会导致死锁

接下来方法都是对lock和unlock的封装

方法二:

std::lock_guard lck(mtx);
构造既锁定,析构会对互斥元进行解锁。
也就是说在子线程函数中执行,使用lock_guard会在函数结束时候自动析构,从而解锁
存在一个问题:若在lock_guard析构调用前,互斥元提前结束,则在析构函数中会出现空指针异常。
C++17可忽略模板参数列表 std::lock_guard lck(mtx);

注意:虽然说上述上锁与解锁十分方便,但是对于数据并不能得到有效保护,因为在使用函数时,可通过指针或引用,来获得保护数据。
因此:不要将对受保护对象的指针或引用传递到锁范围之外。

问题:对于上面两种方式,方法二虽然解决了异常下,锁的自动释放,但是无法解决,线程之间自己产生的死锁,因为无法直接解锁,所以很容易产生死锁
于是产生了方法三。

方法三:

使用unique_lock,存在两个参数//提醒一下,lock_guard也存在两个参数
unique_lock (mutex_type& m, try_to_lock_t tag);

第二个参数:
默认:加锁,需要之前没有clock(),阻塞
defer_lock:初始化一个没有clock的对象,不能提前clock();
try_to_lock:之前没有clock,不会阻塞
adopt_clock:需要提前clock。构造函数也就不需要clock了。

对于unique_lock创建的实例,可使用clock和unlock进行对锁的灵活控制,并且其析构函数自动帮你释放锁。
存在以下成员函数:
own_lock返回是否拥有锁
release释放与锁的相关联,返回mutex指针,加锁的mutex在release,后要利用指针unclock

该函数优点是,可以将所有权转移,也就是不一定要在一个unique_lock吊死。
可通过unique_lock的复制函数转移所有权,也可以通过函数return返回unique_lock对象。

其他工具:

初始化问题:因为某些资源比如文件进行读写需要查看是否初始化,而初始化创建开销不小。因此延迟初始化。
对于这类资源的操作,需要对每个线程查看是否初始化,才能使用。

void func()
{
std:unique_clock<std::mutex> clk(mtx);
if(!资源初始化)
	{
	//存在问题:在此期间,线程1阻塞,其他线程判断没有初始化,进行初始化
		资源初始化
	}
	do_somthing();
}

双重检验锁定模式:

void func()
{
if(!资源初始化)//无锁条件下读取
	{
	//问题:出现条件竞争
	std:unique_clock<std::mutex> clk(mtx);
	if(!资源初始化)//在判断和上锁期间,其他线程可能完成初始化,所以再次判断
		资源初始化
	}
	do_somthing();
}

解决方式:使用std::onec_flag类和std::call_once函数

template <class Fn, class... Args>
 void call_once (once_flag& flag, Fn&& fn, Args&&... args);
std::once_flag resource_flag;
void init_resource()
{
	资源初始化
}
void func()
{
	std::call_once(resource_flag,init_resource);
	do_somthing();
}

另外
C++17所增加的shared_mutex,shared_lock关注点在于读写锁
scoped_lock预防死锁方式为破坏请求并保持条件。

参考博客:http://wjhsh.net/chen-cs-p-13065444.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值