当前位置: 首页 > wzjs >正文

有什么网站招聘做危险高薪工作的新品上市怎么做宣传推广

有什么网站招聘做危险高薪工作的,新品上市怎么做宣传推广,网站设计推广,闵行营销型网站建设std::mutex是一个用于实现互斥访问的类,其具备两个成员函数——lock和unlock 锁的底层实现原理 锁的底层实现是基于原子操作的,这些原子操作是由指令支持的,因为单个指令是不能被中断的 一些与锁的实现有关的原子指令为: 待补充…

std::mutex是一个用于实现互斥访问的类,其具备两个成员函数——lock和unlock

锁的底层实现原理

锁的底层实现是基于原子操作的,这些原子操作是由指令支持的,因为单个指令是不能被中断的

一些与锁的实现有关的原子指令为:

待补充

互斥锁与自旋锁的区别

自旋锁

当前线程在使用获取自旋锁时,如果锁已经被其他线程持有,那么当前会一直忙等待,直到其他线程释放自旋锁。自旋锁会导致CPU时间的浪费,只适用于指令较少的临界区

互斥锁

如果临界区较长,那么使用互斥锁就不合适了,这时需要一种方法,使得当前当前线程获取锁失败时可以陷入睡眠,在锁被其他线程释放时,有机会被唤醒

在调用std::mutex 的lock函数时,如果其他线程已经持有锁,那么当前线程陷入睡眠,让出CPU资源,使得CPU可以去执行其他任务

在调用std::mutex 的unlock函数时,释放锁,同时唤醒由于调用std::mutex 的lock获取锁失败而陷入睡眠的进程

std::mutex与std::lock_guard和std::unique_lock

std::mutex通常搭配std::lock_guard/std::unique_lock使用,以便自动管理加锁、上锁操作

std::lock_guard/std::unique_lock区别在于

  • std::lock_guard在性能上要稍微比std::unique_lock好一点
  • std::unique_lock更加灵活,具有可以主动调用lock/unlock,而std::lock_guard在构造函数中加锁,在析构函数中解锁
  • 使用条件变量时,必须用std::unique_lock

std::mutex源码实现

class mutex : private __mutex_base // 基类为__mutex
{// ...voidlock(){int __e = __gthread_mutex_lock(&_M_mutex); // _M_mutex在基类中。 实际上调用glibc c库的pthread_mutex_lock// ...}voidunlock(){__gthread_mutex_unlock(&_M_mutex);}// ...
}
class __mutex_base  // mutexd的基类
{protected:typedef __gthread_mutex_t                        __native_type;__native_type  _M_mutex = __GTHREAD_MUTEX_INIT;  //  初始化宏constexpr __mutex_base() noexcept = default;// ...}
typedef pthread_mutex_t __gthread_mutex_t;              // _M_mutex的原始类型就是pthread_mutex_t
#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER // 初始化宏是glibc库的初始化宏

从以上代码中可以看到,std::mutex实际上是对glibc pthread mutex实现的一层封装

pthread mutex实现与futex机制

pthread_mutex_t结构体的定义为

typedef union {struct __pthread_mutex_s {int __lock;                // !< 表示是否被加锁,是否存在竞争unsigned int __count;       //!< __kind代表可重入锁时,重复上锁会对__count进行递增。int __owner;                //!< 持有线程的线程ID。unsigned int __nusers;int __kind;                 //!< 上锁类型。int __spins;__pthread_list_t __list;} __data;
} pthread_mutex_t;

pthread_mutex_t.__data._lock的值有3

  • 0, 表示还没有进程/线程获得这把锁

  • 1, 表示有进程/线程已经获得了这个锁

  • 2, 当lock值已经为1,且又有进程/线程要获取这个锁时,将lock置为2,表示发生了竞争

需要注意的是,__data._lock是一个int整型,int类型的数据数写并不是原子的,需要使用原子操作test-and-setcompare-and-swap (CAS)保证对int数据读写的原子性

pthread_mutex_t.__data._kind的是一个32位的整数,库的设计者将这个32字节分成几个部分来提通不同的分类方式

  • 其中的第1到第7位,代表一个锁的类别。

    • PTHREAD_MUTEX_TIMED_NP是mutex的默认类型,它是非递归的,这也是我之后要着重分析的锁类别。而PTHREAD_MUTEX_RECURSIVE_NP则表示可重入锁。其他类别不展开了(能力也不够)

  • 它的第8位表示该锁是用在进程间同步还是线程间同步,通常情况下我们在线程同步中使用mutex,此时只需要将mutex声明在全局数据段即可;但如果是进程间的同步,则需要先开辟一个共享内存,将mutex放入共享内存中,然后不同进程才能操作同一个mutex。

futex机制

glibc nptl引入了futex机制(fast userspace mutex,快速用户空间锁),futex机制是用户空间和内核空间协作完成的,futex机制根据pthread_mutex_t.__data._lock的值进行优化。

pthread mutex的底层实现依赖于futex机制

pthread_mutex_lock实现

对于PTHREAD_MUTEX_TIMED_NP类型的mutexpthread_mutex_lock最终会调用到如下代码

#define __lll_lock(futex, private)                                      \((void)                                                               \({                                                                   \int *__futex = (futex);                                            \if (__glibc_unlikely                                               \(atomic_compare_and_exchange_bool_acq (__futex, 1, 0)))        \{                                                                \if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \__lll_lock_wait_private (__futex);                           \else                                                           \__lll_lock_wait (__futex, private);                          \}                                                                \}))

这里传入的futex即pthread_mutex_t结构体中的__data._lock

atomic_compare_and_exchange_bool_acq是一个CAS操作,可以简写为 CAS(lock, new_val, old_val), 能够达成的效果是,如果old_val == lock,则将new_val赋值给lock,并将old_val返回

这里可以看到,如果__futex值为0,表示没有其他线程加锁,atomic_compare_and_exchange_bool_acq直接返回0,此次加锁操作可以直接在用户态完成,这样的话,就避免了调用系统调用函数时的压栈操作,以及由用户态和内核态之间相互切换的上下文切换操作;若__futex值不为0,则需要进一步调用__lll_lock_wait_private或者__lll_lock_wait,调用futex系统调用进行后续操作。

pthread_mutex_unlock

pthread_mutex_unlock最终会调用到如下代码

#define __lll_unlock(futex, private)                                        \((void)                                                                \({                                                                        \int *__futex = (futex);                                                \int __private = (private);                                                \int __oldval = atomic_exchange_rel (__futex, 0);                        \if (__glibc_unlikely (__oldval > 1))                                \{                                                                \if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \__lll_lock_wake_private (__futex);                           \else                                                           \__lll_lock_wake (__futex, __private);                        \}                                                                \}))

如果__oldval==1,表示只有当前线程持有了锁(这里有一个假设是pthread_mutex_unlock是在正确的情况下使用的,即当前线程已经获取了锁),此时可以直接返回

如果__oldval>=2,表示有其他线程在这个锁上阻塞,由于当前线程释放了锁,此时需要唤醒其他调用了pthread_mutex_lock但被阻塞的线程

futex系统调用

对于futex系统调用,可以看下这篇博客性能打磨手记:记一段 Futex 机制的内核优化之旅 - 魅族内核团队

本文参考:

从C++mutex到futex - 别杀那头猪 - 博客园

http://www.dtcms.com/wzjs/438714.html

相关文章:

  • 网上接网站项目做网站
  • 做淘宝需要知道什么网站吗上海网络推广培训学校
  • mac上安装wordpress排名优化是怎么做的
  • 网站开发建设是否需要经营许可seo推广优势
  • 响应式网站 软件企业软文代写
  • 做网站一台电脑可以吗关键词分析工具
  • 北京手机网站建设公司怎么建立个人网站
  • 做网站找合作伙伴seo搜索如何优化
  • 网站建设模板制作前景个人在线做网站免费
  • 阿里云oss做视频网站宁波seo优化定制
  • 专门做视频的网站吗网络营销怎么做?
  • 重庆网络公司seo工作职位
  • 龙华建网站网络推广专员岗位职责
  • 哪些网站是java做的合肥seo外包平台
  • 一品威客网站是什么做的体彩足球竞彩比赛结果韩国比分
  • 深圳便宜的网站建设怎么注册一个网站
  • 你有网站 我做房东 只收佣金的网站色盲眼中的世界
  • vs2015网站开发seo优化培训学校
  • 网站建站 上海做一个个人网站
  • 非织梦做的网站能仿吗网易疫情实时最新数据
  • 网站公司查询广东seo网站推广代运营
  • wordpress 阿里大于做seo如何赚钱
  • 个人承接网站开发项目百度搜索下载app
  • 快速网站建设seo培训机构哪家好
  • b2c网站建设百度商店应用市场
  • 衡水做wap网站价格百度app下载安装 官方
  • 做网站泰安北京百度推广优化
  • 宁夏考试教育网站百度店面定位怎么申请
  • 微信公众号做视频网站吗博客网站登录入口
  • 外国人做中国英语视频网站吗国内十大软件培训机构