一、互斥量

1.1 互斥量的基本概念

简单来说,一个锁就是一个互斥量,既然是锁,就有两种状态:加锁和解锁,通过加锁>>>操作共享数据>>>解锁的方式,实现保护共享数据。

1.2 互斥量的用法

作用:在给某段代码加锁后,如果其他其他线程需要先等带该段代码执行完,然后解锁后才能继续执行。

头文件 :#include <mutex>

成员函数:lock()   //加锁,unlock()  //解锁

注意点:lock()与unlock()的使用必须成对存在。

 #include <iostream>
#include <mutex>
using namespace std;
int num = ;
mutex my_mutex; //创建一个互斥量
void print1()
{
for (int i = ; i < ; i++)
{
my_mutex.lock();
cout << "thread_1:" << num++ << endl;
my_mutex.unlock();
}
}
void print2()
{
for (int i = ; i < ; i++)
{
my_mutex.lock();
cout << "thread_2:" << num++ << endl;
my_mutex.unlock();
}
} int main()
{
thread thread_1(print1); //打印0-49
thread thread_2(print2); //打印49-99
thread_1.join();
thread_2.join();
system("pause");
return ;
}

还有一种方法,可实现加锁和解锁两个步骤,即用std::lock_guard<mutex> myguard (my_mutex)来代替lock()和unlock(),其原理是,在std::lock_guard构造函数里执行了lock(),在析构函数里执行了unlock()。

 #include <iostream>
#include <mutex>
using namespace std;
int num = ;
mutex my_mutex;
void print1()
{
for (int i = ; i < ; i++)
{
lock_guard<mutex> myguard(my_mutex);
cout << "thread_1:" << num++ << endl;
}
}
void print2()
{
for (int i = ; i < ; i++)
{
lock_guard<mutex> myguard(my_mutex);
cout << "thread_2:" << num++ << endl;
}
} int main()
{
thread thread_1(print1); //打印0-49
thread thread_2(print2); //打印49-99
thread_1.join();
thread_2.join();
system("pause");
return ;
}

二、死锁

仅在存在两个互斥量以上才会出现死锁的现象。例如线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都永远处于挂起状态了。通俗来讲,就是我在等你解锁我才能解锁,你在等我解锁你才能解锁。

 #include <iostream>
#include <mutex>
using namespace std;
int num = ;
mutex my_mutex1;
mutex my_mutex2;
void print1()
{
for (int i = ; i < ; i++)
{
my_mutex1.lock();
/*这里同通常有一段代码,也是用来操作共享数据*/
my_mutex2.lock();
cout << "thread_1:" << num++ << endl;
my_mutex1.unlock();
my_mutex2.unlock();
}
}
void print2()
{
for (int i = ; i < ; i++)
{
my_mutex2.lock();
my_mutex1.lock();
cout << "thread_2:" << num++ << endl;
my_mutex1.unlock();
my_mutex2.unlock();
}
} int main()
{
thread thread_1(print1); //打印0-49
thread thread_2(print2); //打印49-99
thread_1.join();
thread_2.join();
system("pause");
return ;
}

运行结果发现也不会出现任何奔溃出错现象,但是就一直卡在那里,不会继续运行下去了。

解决死锁的方法其实也很简单,只要保证互斥量加锁的顺序一致就可以了。或者使用std::lock(mutex1,mutex2),意思是给这两个互斥量同时上锁。

C++多线程基础学习笔记(五)的更多相关文章

  1. C++基础 学习笔记五:重载之运算符重载

    C++基础 学习笔记五:重载之运算符重载 什么是运算符重载 用同一个运算符完成不同的功能即同一个运算符可以有不同的功能的方法叫做运算符重载.运算符重载是静态多态性的体现. 运算符重载的规则 重载公式 ...

  2. java基础学习笔记五(抽象类)

    java基础学习总结——抽象类 抽象类介绍

  3. Java基础学习笔记(五) - 常用的API

    API介绍 概念:API 即应用编程程序接口.Java API是JDK中提供给我们使用的类说明文档,这些类将底层的代码实现封装.无需关心这些类是如何实现,只需要学习如何使用. 使用:通过API找到需要 ...

  4. Java基础学习笔记五 Java基础语法之面向对象

    面向对象 理解什么是面向过程.面向对象 面向过程与面向对象都是我们编程中,编写程序的一种思维方式.面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程.例如:公司打扫卫生( ...

  5. C++多线程基础学习笔记(四)

    一.创建多个子线程 前面三章讲的例子都是只有一个子线程和主线程,然而实际中有多个子线程.那么下面介绍如何创建多个子线程. #include <iostream> #include < ...

  6. C++多线程基础学习笔记(一)

    下面分三个方面多线程技术的必须掌握一些基本知识. 1.进程 2.线程 3.并发 (1)进程 一个可执行程序运行起来了,即为创建了一个进程.如在电脑上打开了word,就创建了一个word进程,打开QQ, ...

  7. loadrunner基础学习笔记五-场景

    场景目标:模拟10家旅行社同时登录.搜索航班.购买机票.查看航班路线并退出 负载测试是指在典型工作条件下测试应用程序,例如:多家旅行社同时在同一个机票预订系统中预订机票 controller提供所有用 ...

  8. JSP的范围-作用域(web基础学习笔记五)

    JSP的范围(作用域) 在JSP页面中的对象,包括用户创建的对象如JavaBean,都有一个范围属性,这个范围也被叫做“作用域”.范围定义了在什么时间内,在哪一个JSP页面中可以访问这些对象.例如,s ...

  9. C++多线程基础学习笔记(十)

    一.Windows临界区的基本用法 CRITICAL_SECTION my_winsc;              //定义一个Windows的临界区,相当于一个mutex变量 InitializeC ...

随机推荐

  1. Spring Boot教程(四十)使用Flyway来管理数据库版本

    在上面的使用JdbcTemplate一文中,主要通过spring提供的JdbcTemplate实现对用户表的增删改查操作.在实现这个例子的时候,我们事先在MySQL中创建了用户表.创建表的过程我们在实 ...

  2. D. Make a Permutation!(思维)

    D. Make a Permutation! time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  3. PHP依赖管理工具Composer入门

    作者: JeremyWei | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明 网址: http://weizhifeng.net/manage-php-dependency-wi ...

  4. ARTS打卡计划第五周

    Algorithms: https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 采用了map的 ...

  5. tomcat 配置域名部署war 项目

    第一步把打包好的war包 放到 tomcat目录下的webapps 下 截图: 第二步:找到tomcat目录下的server.xml配置文件 server.xml在conf文件夹下面 编辑server ...

  6. EBS 修改系统名称

    修改EBS登录系统的左上角名称 方法: 修改 配置文件: 地点名称  ,在地点层输入相应的名称即可

  7. EBS 修改系统颜色

    1)修改 配置文件: Java 色彩设计,选择相应的颜色 2)清理高速缓存 注:如果不清理缓存,则要等15分钟后才显示变成新设定的颜色

  8. springboot备忘

    1.springboot中有ApplicationRunner类,如果项目中的启动类名称也是ApplicationRunner,单元测试时需要注意:import不要import到springboot的 ...

  9. linux中的i2c控制器驱动应该做些什么?

    答:完成读写功能即可,不要涉及任何针对从设备的特殊操作,这样就可以避免与从设备的代码产生冗余,linux中的i2c控制器驱动就做的特别棒,做好最简单的读写,然后其它的从设备驱动就是直接调用这些最简单的 ...

  10. C#类型转换类(通用类)

    //     /// 类型转换类     /// 处理数据库获取字段为空的情况     ///     public static class DBConvert     {         #reg ...