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行级锁 行级锁又分共享锁和排他锁. 共 ...
随机推荐
- RocketMQ消息模型
rocketmq采用的是发布-订阅的模式,不需要每个消费者维护自己的消息队列,生产者将消息发送到topic,消费者订阅此topic 读取消息. 基本概念: 消息模型:消息模型包括producer,co ...
- c++中多文件的组织
参考书目:visual c++ 入门经典 第七版 Ivor Horton著 第八章 根据书中例子学习使用类的多文件项目. 首先要将类CBox定义成一个连贯的整体,在CBox.H文件中写入相关的类定义, ...
- Maven debug异常:Source not found.
异常 用Maven debug 时出现了Source not found.,在调试过程中尝试添加源码也没有效果 解决方案 先把当前正在运行中的项目停止 右键项目 -> Debug As -> ...
- 五、Shell运算
整数值运算 使用expr命令:只能做整数运算,默认返回计算结果 格式: expr 整数1 运算符 整数2 ... 整数值可以有变量提供,直接给出运算结果 + 加法 expr 43 + 21 .expr ...
- ceph问题
问题1: [root@admin-node my-cluster]# ceph -s cluster 4ca35731-2ccf-47fb-9f06-41fae858626d health HEALT ...
- ICC中对Skew进行Debug的好工具--Interactive CTS Window
本文转自:自己的微信公众号<集成电路设计及EDA教程> 以后打算交替着推送多种EDA工具的教程而不只是单纯针对某个工具,依次来满足不同粉丝的需求. 这里分享一篇多年之前写的推文,虽然时间 ...
- mysql 5.7中 count(0) count(*) count(主键) count(非空字段)效率比较
mysql count(0) count(*) count(主键) count(非空字段) 效率比较 写代码的时候经理在背后说了一句count(0)的效率高于count(*) ,索性全部测试了一下 结 ...
- ASP.NET Core on K8S 入门学习系列文章目录
一.关于这个系列 自从2018年底离开工作了3年的M公司加入X公司之后,开始了ASP.NET Core的实践,包括微服务架构与容器化等等.我们的实践是渐进的,当我们的微服务数量到了一定值时,发现运维工 ...
- 如何为wordpress 添加favicon
制做一张16px×16px(像素)大小的图片命名favicon并修改扩展名为.ico,即favicon.ico文件! 方法1:将favicon.ico图标上传到WordPress博客空间的根目录(方法 ...
- EF core (code first) 通过自动迁移实现多租户数据分离 :按Schema分离数据
前言 本文是多租户系列文章的附加操作文章,如果想查看系列中的其他文章请查看下列文章 主线文章 Asp.net core下利用EF core实现从数据实现多租户(1) Asp.net core下利用EF ...