C++关于锁的总结(一)
C++关于锁的总结(一)
线程中的锁分为两种,互斥锁和共享锁。
相关的头文件有<mutex>,<shared_mutex>,前者具有std::unique_lock操作,用于实现互斥功能,后者具有std::shared_lock操作,用于完成共享锁操作。
这里先讨论std::shared_mutex这个类。
共享锁
如果需要使用共享锁,则需要使用到std::shared_mutex这个类。具体讲解见这里
该锁可用于保护被多个线程同时访问的共享数据。
std::shared_mutex有两种访问级别:
- 共享:多个线程可以共享这个锁的拥有权。一般用于数据的读操作,防止数据被写修改。
- 互斥:仅仅一个线程可以拥有这个锁。一般用于写操作。
如果一个线程已经获取了互斥锁,则其他线程都无法获取该锁。
如果一个线程已经获取了共享锁,则其他任何线程都无法获取互斥锁,但是可以获取共享锁。
说到这里,为了实现该锁的互斥和共享,不得不介绍std::shared_lock和std::unique_lock这两个模板。前者定义在<shared_mutex>,后着定义在<mutex>中。
在下面的代码中均以测试过,编译选项为--std=c++1z -pthread;
由于c++中的cout不是线程安全的函数,所以给cout输出加上了互斥锁。
共享锁的代码示例
#include <shared_mutex>
#include <mutex>
#include <iostream>
#include <thread>
#include <chrono>
std::shared_mutex test_lock;
std::mutex cout_lock;
int arr[3] = {11, 22, 33};
void unique_lock_demo(int id)
{
std::unique_lock lock{test_lock};
for(int i =0; i < 3; i++)
{
arr[i] = i + 100 * id;
}
for(int i = 0; i < 3; i++)
{
std::unique_lock pl(cout_lock);
std::cout << "In unique: " << id << ": " << arr[i] << std::endl;
pl.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void shared_lock_demo(int id)
{
std::shared_lock lock{test_lock};
for(int i = 0; i < 3; i++)
{
std::unique_lock pl(cout_lock);
std::cout << "In shared " << id << ": " << arr[i] << std::endl;
pl.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::thread t3(unique_lock_demo,3);
std::thread t4(unique_lock_demo,4);
std::thread t1(shared_lock_demo,1);
std::thread t2(shared_lock_demo,2);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
输出为:
In unique: 3: 300
In unique: 3: 301
In unique: 3: 302
In shared 1: 300
In shared 2: 300
In shared 1: 301
In shared 2: 301
In shared 1: 302
In shared 2: 302
In unique: 4: 400
In unique: 4: 401
In unique: 4: 402
从这个输出可以看出:
如果一个线程已经获取了共享锁,则其他任何线程都无法获取互斥锁,但是可以获取共享锁。
从这个输出可以看出,验证了如果一个线程已经获取了互斥锁,则其他线程都无法获取该锁。
注:关于上述代码有的平台运行不了,可以运行下面的代码
#include <shared_mutex>
#include <mutex>
#include <iostream>
#include <thread>
#include <chrono>
std::shared_mutex test_lock;
std::mutex cout_lock;
int arr[3] = {11, 22, 33};
void unique_lock_demo(int id)
{
std::unique_lock<std::shared_mutex> lock(test_lock);
for(int i =0; i < 3; i++)
{
arr[i] = i + 100 * id;
}
for(int i = 0; i < 3; i++)
{
std::unique_lock<std::mutex> pl(cout_lock);
std::cout << "In unique: " << id << ": " << arr[i] << std::endl;
pl.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void shared_lock_demo(int id)
{
std::shared_lock<std::shared_mutex> lock(test_lock);
for(int i = 0; i < 3; i++)
{
std::unique_lock<std::mutex> pl(cout_lock);
std::cout << "In shared " << id << ": " << arr[i] << std::endl;
pl.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::thread t3(unique_lock_demo,3);
std::thread t1(shared_lock_demo,1);
std::thread t2(shared_lock_demo,2);
std::this_thread::sleep_for(std::chrono::seconds(4));
std::thread t4(unique_lock_demo,4);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
C++关于锁的总结(一)的更多相关文章
- 使用redis构建可靠分布式锁
关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- java中的锁
java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...
- 分布式锁1 Java常用技术方案
前言: 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.所以自己结合实际工作中的一些经验和网上看到的一些资 ...
- 如何在高并发环境下设计出无锁的数据库操作(Java版本)
一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Jav ...
- 如何定位Oracle数据库被锁阻塞会话的根源
首先再次明确下,数据库因为要同时保证数据的并发性和一致性,所以操作有锁等待是正常的. 只有那些长时间没有提交或回滚的事物,阻塞了其他业务正常操作,才是需要去定位处理的. 1.单实例环境 2.RAC环境 ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- Android 死锁和重入锁
死锁的定义: 1.一般的死锁 一般的死锁是指多个线程的执行必须同时拥有多个资源,由于不同的线程需要的资源被不同的线程占用,最终导致僵持的状态,这就是一般死锁的定义. package com.cxt.t ...
- Xcode 锁终端
锁终端 输入: <1>cd /Applications/Xcode.app 回车 结果显示: Xcode.app 输入: <2>sudo chown -hR root:whee ...
- mysql 行级锁的使用以及死锁的预防
一.前言 mysql的InnoDB,支持事务和行级锁,可以使用行锁来处理用户提现等业务.使用mysql锁的时候有时候会出现死锁,要做好死锁的预防. 二.MySQL行级锁 行级锁又分共享锁和排他锁. 共 ...
随机推荐
- Promise函数的使用
最近在做批量打印并监控显示打印进度的功能,用到了很多异步函数,很多异步函数嵌套在回调函数里面,层层嵌套,导致代码可阅读性与可维护性变得十分糟糕,而且由于都是异步执行的函数,无法知道什么时候能回调结束, ...
- layui数据表格及分页
一.前端部分 html只需要放一个有id的div就行了,方便js获取渲染区域 <div id="data_grid" lay-filter="demo" ...
- Iptables和Firewall-selinux
一.Iptables防火墙 ---------- **三表五链:**三表: filter过滤表 nat转换表 mangle表五链: PREROUTING--->在进行路由选择前处理数据包 INP ...
- 使用abp框架与vue一步一步写我是月老的小工具(1)
一.前言 因为工作的原因,我真正写代码的时间很少,技术面广但深度一直不够,兴趣广泛但缺乏专业精神.以前一直想用asp.net写一款框架,用来在企业开发过程中做一些基础工作,不过后来我找到abp这个框架 ...
- centos6.8安装lnmp
一.配置CentOS 第三方yum源(CentOS默认的标准源里没有nginx软件包) [root@localhost ~]# yum install wget #安装下载工具wget[root@lo ...
- 读取sysTreeview32和SysListView32
#include <stdio.h> #include <windows.h> #include <commctrl.h> int main(void) { /* ...
- 命令行压缩解压缩一 7z
命令行压缩解压缩一 7z 1) 简介 7z,全称7-Zip, 是一款开源软件.是目前公认的压缩比例最大的压缩解压缩软件. 主页:http://www.7-zip.org/ 中文主页:http: ...
- Zabbix监控实现跨区域跨网络监控数据
Zabbix监控实现跨区域跨网络监控数据 环境: 公司现有服务器10台,其中5台服务器有一台安装了zabbix,并且这5台服务器处于一个网络,只有一台服务器有公网ip, 另外的5台处于另一个网络,仅有 ...
- 移动端H5优化
H5前端优化收藏的网址: https://zhuanlan.zhihu.com/p/25176904 http://tgideas.qq.com/webplat/info/news_version3/ ...
- num09---建造者模式
建造者模式: 核心思想:将产品 和 产品建造过程解耦