C++ 互斥量-mutex 详解

从C++11开始,标准库就开始有了并发支持库,其中就包括mutex 互斥量的支持。

mutex提供用于保护共享数据免受从多个线程同时访问的功能。下面是一个简单的例子:

#include 
#include 
#include 
using namespace std;
mutex smutex;
long sumval = 0;
void threadsum()
{
  for (long i=0;i<100000;i++)
  {
    smutex.lock();
    sumval++;
    smutex.unlock();
  }
}
int main()
{
  for (int i=0;i<10;i++)
  {
    thread(threadsum).detach();
  }
  this_thread::sleep_for(1000ms);
  std::cout << "Sum Value:" << sumval << std::endl;
}

如果没有互斥量smutex的支持,Sum Value的结果是不固定的:

Sum Value:347214

mutex的用法也比较简单:

smutex.lock();  //锁定互斥量,如果已被锁定,则无限等待
//xxx  锁定区域内的代码,多线程安全
smutex.unlock(); //解除锁定

为了避免无限等待问题,还提供try_lock指令,如果可以锁定,则返回true,否则 false

还是刚才的例子:

void threadsum()
{
  for (long i=0;i<100000;i++)
  {
    for (;;)
    {
      if (smutex.try_lock())
      {
        sumval++;
        smutex.unlock();
        break;
      }
      else
      {
        std::cout << "try_lock NG retry!
";
      }
    }
  }
}

但是还是不太灵活,所以C++11有提供了timed_mutex类,这样就可以提供有超时特性的 mutex。相对于mutex,增加了两个成员函数 try_lock_for以及try_lock_until

t_mutex.try_lock_for(100ms); //尝试在100ms内锁定互斥量,如果成功返回true
auto now=std::chrono::steady_clock::now();
t_mutex.try_lock_until(now + 100ms);  //尝试在now时间的基础上叠加100ms内锁定互斥量,如果成功返回true

另外的,由于互斥的特性,在已经锁定互斥量的基础上,再次尝试锁定,会死锁或者异常。在某些特殊的情况不利于代码快速编写。

所以C++11还提供了递归锁——recursive_mutex以及recursive_timed_mutex。

对于如下代码,采用常规mutex会异常,换成递归锁正常执行,方便很多递归函数的互斥。

std::mutex addMutex;
//std::recursive_mutex addMutex;
void addfun(int &nowt)
{
  addMutex.lock();
  if(nowt>=0)
  {
    nowt--;
    std::cout << "nowt--
";
    addfun(nowt);
  }
  addMutex.unlock();
}

很多时候互斥只需求锁定修改权限,而读取权限不单独锁定,即读写锁,C++提供了以下类:

  • shared_timed_mutex(C++14起)---带超时的读写锁
  • shared_mutex(C++17起) ---读写锁
class RWMutex {
public:
  RWMutex() = default;

  // 能同时读计数器的值。
  void read(unsigned int &res) 
  {
    mutex_.lock_shared();
    std::cout << "Enter Read
";
    res= value_;
    //this_thread::sleep_for(1000ms);
    mutex_.unlock_shared();
  }

	// 只有一个能写
  void write() {
    mutex_.lock();
    std::cout << "Enter Write
";
    value_++;
    this_thread::sleep_for(1000ms);
    mutex_.unlock();
  }


private:
  std::shared_mutex mutex_;
  unsigned int value_ = 0;
};

int main() {
  RWMutex mutextest;

  auto testthread = [&]() {
    for (int i = 0; i < 3; i++) {
      //mutextest.write();
      unsigned int res;
      mutextest.read(res);
      std::cout << "threadid:"<threadlist;
  for (int i=0;i<10;i++)
  {
    threadlist.emplace_back(std::thread(testthread));
  }
	
  for (int i = 0; i < 10; i++)
  {
    threadlist[i].join();
  }
}

如上例展示,增加了lock_sharedunlock_sharedtry_lock_shared以及

try_lock_shared_for、try_lock_shared_until等系列成员函数。

The End~


C++ 互斥量——mutex 详解

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章