首页 > 编程语言 >C++多线程中互斥量的使用

C++多线程中互斥量的使用

时间:2023-08-04 14:57:24浏览次数:48  
标签:std include lock C++ 互斥 线程 多线程 上锁

多线程中互斥信号量(Mutex)的使用

1.0 互斥量的基本概念

1.1 Example

\(\quad\)首先我们要明白,为什么会有互斥信号量的出现,在多线程编程中,不同的线程之间往往要对同一个数据进行操作,如果该数据是只读的,当然不会出现什么问题,但是如果两个线程同时对某个数据进行写操作,则可能出现难以预料的事情。

  • 我们来看一个简单的操作
#include <atomic>
#include <iostream>
#include <thread>
#include <chrono>
#include <pthread.h>
using namespace std;

int i = 0;
const int maxCnt = 1000000;
void mythread()
{
  for (int j = 0; j < maxCnt; j++)
  {
    i++;  // 线程同时操作变量
  }
}

int main()
{
  auto begin = chrono::high_resolution_clock::now();
  thread t1(mythread);
  thread t2(mythread);
  t1.join();
  t2.join();
  auto end = chrono::high_resolution_clock::now();
  cout << "i=" << i << endl;
  cout << "time: "
       << chrono::duration_cast<chrono::microseconds>(end - begin).count() *
              1e-6
       << "s" << endl;  // 秒计时
}

可以看到在我的电脑上程序的输出为

i=1022418
time: 0.010445s

很明显和我们预想的结果是不一致的,我们使用两个线程同时对该变量进行加法操作,根据运行此书来计算,结果因该为 2000000,但事实上却不是这样的,这就是因为有多个线程在对同一个变量进行写操作的时候会出现难以排查的问题,意想不到的结果。此时mutex就派上用场了,我们对程序进行稍微的改动。

std::mutex var_mutex;

int i = 0;
const int maxCnt = 1000000;
void mythread()
{
  for (int j = 0; j < maxCnt; j++)
  {
    var_mutex.lock();
    i++;  // 线程同时操作变量
    var_mutex.unlock();
  }
}

此时再运行程序可以发现结果如下,这是符合我们的预期的。

i=2000000
time: 0.09337s

1.2 互斥量用法解释

\(\quad\)互斥量就是个类对象,可以理解成一把锁,多个线程尝试用lock()成员函数来加锁,从而获得对数据的访问权限,或者说读写权限,其实就是继续执行代码的权限。最终只有一个线程能锁定成功,如果没有锁成功,那么流程将卡在lock()这里不断尝试去锁定。所以我们在使用

标签:std,include,lock,C++,互斥,线程,多线程,上锁
From: https://www.cnblogs.com/weihao-ysgs/p/cpp_mutex.html

相关文章

  • 使用Vue+Vite搭建在线 C++ 源代码混淆工具,带在线实例
    就酱紫github开源地址:https://github.com/dffxd-suntra/cppdgithub在线实例:https://dffxd-suntra.github.io/cppd/预览图片:长截屏背景图重复了,抱歉......
  • 为什么有了gil锁还要互斥锁,进程,线程和协程 ,什么是鸭子类型
    1为什么有了gil锁还要互斥锁-gil锁,全局解释器锁,线程需要运行需要得到gil锁,gil锁不能控制用户级别的安全-#互斥锁,为了保证多线程并发操作数据而设置的锁,保证在加锁和释放锁之间,其他线程不能操作,让并行变成串行,牺牲效率-起两个线程。执行任务,x=x+1,x开始等于0-1第一个线程过来......
  • 第三阶段C++提高编程(黑马程序员)——Day10
    4STL-函数对象4.1函数对象4.1.1函数对象概念概念:重载函数调用操作符的类,其对象常称为函数对象函数对象使用重载的()时,行为类似函数调用,也叫仿函数本质:函数对象(仿函数)是一个类,不是一个函数4.1.2函数对象使用特点:函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值函数......
  • Java多线程总结(超详细总结)
    (Java多线程总结)1.创建线程的方式方式1继承于Thread类创建一个继承于Thread类的子类重写Thread类的run()-->将此线程执行的操作声明在run()中创建Thread类的子类的对象4.通过此对象调用start()例子:遍历100以内的所有的偶数classMyThreadextendsThread{//......
  • C++11 同步与互斥
    C++11同步与互斥1.std中的锁1.1锁是实现互斥的方法,在std中实现了多种基本锁如下:std::mutex:最基本的互斥锁,只能在同一线程中进行加锁和解锁操作。std::recursive_mutex:递归互斥锁,允许同一线程多次加锁,但必须在同一线程中解锁相同次数。std::timed_mutex:定时互斥锁,允......
  • C++ Toolkit zz
    所谓“工欲善其事,必先利其器”,从程序员的角度来讲,好工具的使用总会给人带来事半功倍的效果。面对众多工具/软件,我们应该如何取舍呢。前不久,笔者在csdn的c++论坛发了一篇贴文,以期能征求大家的广泛意见,得到了不错的反响。本文在对该贴进行整理的基础上,又做了一些补充。在这里要特别......
  • c++算法之离散化
    什么是离散化?离散化,故离散数学,其中的“离散”就是不连续的意思。离散化可以保持原数值之间相对大小关系不变的情况下将其映射成正整数。也就是给可能用到的数值按大小关系分配一个编号,来代替原数值进行各种操作。离散化步骤:1.排序2.去重3.归位举一个例子:将{4000,201,11......
  • C++ 重写、隐藏、覆盖
    1.基本概念:1.1重载重载:是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。示例:classA{public:voidtest(inti);voidtest(doublei);//overloadvoidtest(inti,doubl......
  • c++ 箭头运算符
    C++中箭头运算符的含义与用法讲解_C语言_脚本之家(jb51.net)C++中箭头运算符->,相当于把解引用和成员访问符两个操作符结合在一起,换句话说,p->func()和(*p).func()所表示的意思一样。例如:12345classA{public:func();}123456clas......
  • c++数组作为函数参数
    intsum_arr(intarr[],intn){ inttotal=0; for(inti=0;i<n;i++){ total=total+arr[i]; } returntotal;}方括号指出arr是一个数组,而方括号为空则表明,可以将任何长度的数组传递给该函数,n代表数组的长度。实际数组名就是指针,解释为其第一个元素的地址。int......