加入收藏 | 设为首页 | 会员中心 | 我要投稿 新余站长网 (https://www.0790zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

面试多线程同步,你必须要思考的问题

发布时间:2019-08-01 09:54:54 所属栏目:评测 来源:佚名
导读:ReentrantLock的实现网上有很多文章了,本篇文章会简单介绍下其java层实现,重点放在分析竞争锁失败后如何阻塞线程。 因篇幅有限,synchronized的内容将会放到下篇文章。 Java Lock的实现 ReentrantLock是jdk中常用的锁实现,其实现逻辑主语基于AQS(juc包

pthread_mutex_unlock.c

  1. int 
  2. internal_function attribute_hidden 
  3. __pthread_mutex_unlock_usercnt (mutex, decr) 
  4.  pthread_mutex_t *mutex; 
  5.  int decr; 
  6.  if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP) 
  7.  == PTHREAD_MUTEX_TIMED_NP) 
  8.  { 
  9.  /* Always reset the owner field. */ 
  10.  normal: 
  11.  mutex->__data.__owner = 0; 
  12.  if (decr) 
  13.  /* One less user. */ 
  14.  --mutex->__data.__nusers; 
  15.  /* Unlock. */ 
  16.  lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); 
  17.  return 0; 
  18.  } 
  19.  } 

pthread_mutex_unlock将mutex中的owner清空,并调用了lll_unlock方法

lowlevellock.h

  1.  #define __lll_unlock(futex, private)  
  2.  ((void) ({  
  3.  int *__futex = (futex);  
  4.  int __val = atomic_exchange_rel (__futex, 0);  
  5.   
  6.  if (__builtin_expect (__val > 1, 0))  
  7.  lll_futex_wake (__futex, 1, private);  
  8.  })) 
  9. #define lll_unlock(futex, private) __lll_unlock(&(futex), private) 
  10. #define lll_futex_wake(ftx, nr, private)  
  11. ({  
  12.  DO_INLINE_SYSCALL(futex, 3, (long) (ftx),  
  13.  __lll_private_flag (FUTEX_WAKE, private),  
  14.  (int) (nr));  
  15.  _r10 == -1 ? -_retval : _retval;  
  16. }) 

lll_unlock分为两个步骤:

  1. 将futex设置为0并拿到设置之前的值(用户态操作)
  2. 如果futex之前的值>1,代表存在锁冲突,也就是说有线程调用了FUTEX_WAIT在休眠,所以通过调用系统函数FUTEX_WAKE唤醒休眠线程

FUTEX_WAKE在上一篇文章有分析,futex机制的核心是当获得锁时,尝试cas更改一个int型变量(用户态操作),如果integer原始值是0,则修改成功,该线程获得锁,否则就将当期线程放入到 wait queue中,wait queue中的线程不会被系统调度(内核态操作)。

futex变量的值有3种:0代表当前锁空闲,1代表有线程持有当前锁,2代表存在锁冲突。futex的值初始化时是0;当调用try_lock的时候会利用cas操作改为1(见上面的trylock函数);当调用lll_lock时,如果不存在锁冲突,则将其改为1,否则改为2。

  1. #define __lll_lock(futex, private)  
  2.  ((void) ({  
  3.  int *__futex = (futex);  
  4.  if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex,  
  5.  1, 0), 0))  
  6.  {  
  7.  if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)  
  8.  __lll_lock_wait_private (__futex);  
  9.  else  
  10.  __lll_lock_wait (__futex, private);  
  11.  }  
  12.  })) 
  13. #define lll_lock(futex, private) __lll_lock (&(futex), private) 
  14. void 
  15. __lll_lock_wait_private (int *futex) 
  16. //第一次进来的时候futex==1,所以不会走这个if 
  17.  if (*futex == 2) 
  18.  lll_futex_wait (futex, 2, LLL_PRIVATE); 
  19. //在这里会把futex设置成2,并调用futex_wait让当前线程等待 
  20.  while (atomic_exchange_acq (futex, 2) != 0) 
  21.  lll_futex_wait (futex, 2, LLL_PRIVATE); 

pthread_cond_timedwait

(编辑:新余站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读