park方法用POSIX的pthread_cond_timedwait方法阻塞线程,调用pthread_cond_timedwait前需要先获得锁,因此park主要流程为:
- 调用pthread_mutex_trylock尝试获得锁,如果获取锁失败则直接返回
- 调用pthread_cond_timedwait进行等待
- 调用pthread_mutex_unlock释放锁
另外,在阻塞当前线程前,会调用OSThreadWaitState的构造方法将线程状态设置为CONDVAR_WAIT,在Jvm中Thread状态枚举如下
- enum ThreadState {
- ALLOCATED, // Memory has been allocated but not initialized
- INITIALIZED, // The thread has been initialized but yet started
- RUNNABLE, // Has been started and is runnable, but not necessarily running
- MONITOR_WAIT, // Waiting on a contended monitor lock
- CONDVAR_WAIT, // Waiting on a condition variable
- OBJECT_WAIT, // Waiting on an Object.wait() call
- BREAKPOINTED, // Suspended at breakpoint
- SLEEPING, // Thread.sleep()
- ZOMBIE // All done, but not reclaimed yet
- };
Linux的timedwait
由上文我们可以知道LockSupport.park方法最终是由POSIX的 pthread_cond_timedwait的方法实现的。 我们现在就进一步看看pthread_mutex_trylock,pthread_cond_timedwait,pthread_mutex_unlock这几个方法是如何实现的。
Linux系统中相关代码在glibc库中。
pthread_mutex_trylock
先看trylock的实现, 代码在glibc的pthread_mutex_trylock.c文件中,该方法代码很多,我们只看主要代码
- //pthread_mutex_t是posix中的互斥锁结构体
- int
- __pthread_mutex_trylock (mutex)
- pthread_mutex_t *mutex;
- {
- int oldval;
- pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
- switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex),
- PTHREAD_MUTEX_TIMED_NP))
- {
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- case PTHREAD_MUTEX_TIMED_NP:
- case PTHREAD_MUTEX_ADAPTIVE_NP:
- /* Normal mutex. */
- if (lll_trylock (mutex->__data.__lock) != 0)
- break;
- /* Record the ownership. */
- mutex->__data.__owner = id;
- ++mutex->__data.__nusers;
- return 0;
- }
- }
- //以下代码在lowlevellock.h中
- #define __lll_trylock(futex)
- (atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0)
- #define lll_trylock(futex) __lll_trylock (&(futex))
mutex默认用的是PTHREAD_MUTEX_NORMAL类型(与PTHREAD_MUTEX_TIMED_NP相同); 因此会先调用lll_trylock方法,lll_trylock实际上是一个cas操作,如果mutex->data.lock==0则将其修改为1并返回0,否则返回1。
如果成功,则更改mutex中的owner为当前线程。
pthread_mutex_unlock (编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|