c++ multithread and lock--part 3

本文将对库进行详细的介绍
多线程可以利用cpu并发执行提高运行效率,但是很明显会存在一个问题,那就是多个线程同时访问共享数据的时候,存在数据不一致的风险,这种现象也就是我们常说的“数据不安全”。为了保证数据的安全性,通常我们需要在访问共享数据的时候进行加锁操作,加锁可以保证在同一时刻在同一时刻只有一个线程对数据进行操作。TODO:MESI

mutex互斥锁

mutex是在多线程中用来保证数据一致性最简单的一种方式,我们先来看一下mutex到底是个什么东西。
mutex是命名空间std下面的一个类,使用mutex需要引入文件,但是在mutex文件中本身没有mutex类的定义。中引入了文件,类mutex就是在< std_mutex.h>中定义的, (注意:本系列文章示例代码的运行及代码分析都是基于MacOS,后续不再说明)。
mutex继承自_mutex_base类,在_mutex_base类中定义了一个_gthread_mutex_t类型的_m_Mutex变量,_gthread_mutex_t实质上是源码中自定义的int类型的别名。所以显而易见,mutex便自动的拥有了_m_Mutex变量。
mutex构造对象时会先调用_mutex_base类的构造函数,而在_mutex_base类的构造函数中会初始化_m_Mutex的值。
mutex总共对外提供了四个成员函数,他们分别是:

  • lock():lock()方法里面的逻辑是
      int __e = __gthread_mutex_lock(&_M_mutex);
      if (__e)
      __throw_system_error(__e);

而_gthread_mutex_lock(_gthread_mutex_t *_mutex)方法中的逻辑是:

  while (__sync_lock_test_and_set (_mutex, 1))
    asm volatile ("s_sleep\t1" ::: "memory");
  return 0;

其中__sync_lock_test_and_set(_mutex, 1)是一个原子操作,用于将1写入_mutex,同时返回_mutex之前的值,当_mutex为1,即锁被占用时,会在此阻塞,直到_mutex被其他线程释放。由上述两段代码可知,lock()是阻塞式访锁模式。

  • try_lock():该方法跟lock()方法类似也是获取锁的方法,其包含逻辑为
return !__gthread_mutex_trylock(&_M_mutex);

继续跟,发现__gthread_mutex_trylock方法里的逻辑为

__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
{
  return __sync_lock_test_and_set (__mutex, 1);
}

__gthread_mutex_trylock中没有循环,只是访问一次即返回。所以我们可以很清晰的知道,try_lock()是非是阻塞的。

  • unlock():释放锁的方法。
  • native_handle():方法里的逻辑是
return &_M_mutex

也就是获取_M_mutex的地址。

你可能感兴趣的:(c++ multithread and lock--part 3)