c++ 学习之 多线程(五)互斥量 mutex

c++ 学习之 多线程(五)互斥量 mutex

前言

在多线程的应用中,常常会涉及到共享数据,当我们直接对共享数据进行操作时,比如多个进程同时进行写操作时,就会发生异常,接下来我们引入互斥量来解决这个问题。

正文

1.lock() 与 unlock()

先来看一下这个代码:

#include<thread>
#include<stdio.h>
#include<mutex>
using namespace std;
void fun(int& num)
{
	 for (int i = 0; i < 100000; i++)
	 {
	  num++;
	 }
}
int main()
{
	 int num = 0;
	 thread t1(fun,ref(num));
	 thread t2(fun, ref(num));
	 t1.join();
	 t2.join();
	 printf("%d\n", num);
}

输出结果:131341

输出结果时131341,不是咱们预期的200000。在这个例子中num就是t1线程和t2线程的共享数据,我们同时对其进行写操作,比如在t1线程对num进行++操作时,t2线程也对其进行++操作,上一次的操作没有结束,下一次操作有开始了,这样很显然没有办法让其正常的执行完200000次++,就出现了这样的问题。我们可以通过添加互斥量来解决这个问题。

#include<thread>
#include<stdio.h>
#include<mutex>
using namespace std;
mutex m;
void fun(int& num)
{
	 for (int i = 0; i < 100000; i++)
	  {
	   m.lock();
	   num++;
	   m.unlock();
	  }
}
int main()
{
	  int num = 0;   
          thread t1(fun,ref(num));
	  thread t2(fun, ref(num));
	  t1.join();
	  t2.join();
	  printf("%d\n", num);
} 

输出结果: 200000
这样我们就得到了我们预期的200000了。那么互斥量是怎样完成这样的功能的呢?其实我们可以把互斥量理解成一把锁,一但我们调用 lock()时,互斥量会尝试去lock,如果lock成功,其他线程再次调用lock时,就会lock失败,失败后就会阻塞到当前位置,直到 lock成功才会执行下面的语句。当我们对共享数据的操作结束后,调用 unlock()来解锁, 这样其他线程才可以 lock 成功。
通俗的理解,调用lock后我们获得共享数据的使用权,用完之后,调用unlock让出使用权,供其他线程使用,如此,我们可以保证在某一时间内,只有一个线程操作着共享数据。

2.try_lock()

try_lock() 也是mutex类的成员函数,调用 try_lock() 时,互斥量会尝试lock,如果lock成功,返回true,否则返回false。注意,当返回true时,该互斥量已经lock了,无需再次调用lock,释放时直接调用unlock即可。

3.注意

(一)lock 和 unlock 必须对应出现,也就是lock后一定要unlock,unlock之前一定要lock。 尤其是在判断分支中,千万别忘记unlock
(二) 同一线程中同一互斥量只能lock一次,在unlock后才可再次lock,不然会抛出异常。
(三)lock与unlock必须对同一互斥量操作才会有效,比如m1调用了lock,m2调用unlock是没用的。

发布了10 篇原创文章 · 获赞 6 · 访问量 411

猜你喜欢

转载自blog.csdn.net/weixin_45074185/article/details/104598314
今日推荐