歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java 中的 wait 和 notify 實現的源碼分析

Java 中的 wait 和 notify 實現的源碼分析

日期:2017/3/1 10:40:22   编辑:Linux編程

在Oracle JVM 1.6 裡面實現的object的wait 和notify方法是在synchronizer.cpp裡實現。

先介紹2個對象:

1. ObjectMonitor 對象 主要用來監視創立的Object

在synchronizer.cpp 裡定義了,ObjectMonitor 的對象,我們來看ObjectMonitor的對象的結構體

  1. ObjectMonitor::ObjectMonitor() {
  2. _header = NULL;
  3. _count = 0;
  4. _waiters = 0,
  5. _recursions = 0;
  6. _object = NULL;
  7. _owner = NULL;
  8. _WaitSet = NULL;
  9. _WaitSetLock = 0 ;
  10. _Responsible = NULL ;
  11. _succ = NULL ;
  12. _cxq = NULL ;
  13. FreeNext = NULL ;
  14. _EntryList = NULL ;
  15. _SpinFreq = 0 ;
  16. _SpinClock = 0 ;
  17. OwnerIsThread = 0 ;
  18. }

每個object的對象裡 markOop->monitor() 裡可以保存ObjectMonitor的對象。

建立ObjectMonitor的算法:

如果不存在,可以向Thread 的ObjectMonitor 的對象列表中Allocate free objectMonitor 對象。

每個線程都有ObjectMonitor 的free和used的objectMonitor對象列表,如果沒有free objectMonitor對象列表,將向global 中ListLock Allocate為了提高效率。

2. ObjectWaiter 對象

ObjectWaiter 對象

  1. class ObjectWaiter : public StackObj {
  2. public:
  3. enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
  4. enum Sorted { PREPEND, APPEND, SORTED } ;
  5. ObjectWaiter * volatile _next;
  6. ObjectWaiter * volatile _prev;
  7. Thread* _thread;
  8. ParkEvent * _event;
  9. volatile int _notified ;
  10. volatile TStates TState ;
  11. Sorted _Sorted ; // List placement disposition
  12. bool _active ; // Contention monitoring is enabled
  13. public:
  14. ObjectWaiter(Thread* thread) {
  15. _next = NULL;
  16. _prev = NULL;
  17. _notified = 0;
  18. TState = TS_RUN ;
  19. _thread = thread;
  20. _event = thread->_ParkEvent ;
  21. _active = false;
  22. assert (_event != NULL, "invariant") ;
  23. }
  24. void wait_reenter_begin(ObjectMonitor *mon) {
  25. JavaThread *jt = (JavaThread *)this->_thread;
  26. _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
  27. }
  28. void wait_reenter_end(ObjectMonitor *mon) {
  29. JavaThread *jt = (JavaThread *)this->_thread;
  30. JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
  31. }
  32. };

ObjectWaiter 對象裡存放thread(線程對象) 和 ParkEvent(線程的unpark), 每一個等待鎖的線程都會有一個ObjectWaiter對象.

而objectwaiter是個雙向鏈表結構的對象。

我們可以看到在ObjectMonitor對象裡有2個隊列成員_WaitSet 和 _EntryList 存放的就是ObjectWaiter

_WaitSet:

主要存放所有wait的線程的對象,也就是說如果有線程處於wait狀態,將被掛入這個隊列

_EntryList:

所有在等待獲取鎖的線程的對象,也就是說如果有線程處於等待獲取鎖的狀態的時候,將被掛入這個隊列。

Wait 方法實現:

ObjectSynchronizer::wait方法

通過object的對象中找到ObjectMonitor對象

調用方法

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)

通過ObjectMonitor::AddWaiter調用把新建立的ObjectWaiter對象放入到 _WaitSet 的隊列的末尾中

然後在ObjectMonitor::exit釋放鎖,接著 thread_ParkEvent->park 也就是wait

Notify方法的實現:

ObjectSynchronizer::notify方法

調用ObjectSynchronizer::inflate

object的對象中找到ObjectMonitor對象

然後調用方法ObjectMonitor::notify

調用ObjectMonitor::DequeueWaiter 摘除第一個ObjectWaiter對象從_WaitSet 的隊列中

並把這個ObjectWaiter對象放入_EntryList中,_EntryList 存放的是ObjectWaiter的對象列表,列表的大小就是那些所有在等待這個對象鎖的線程數。

注意這裡並沒有調用ObjectMonitor::exit釋放鎖

NotifyALL和Notify 的區別就是

通過遍歷調用ObjectMonitor::DequeueWaiter,把所有的_WaitSet的隊列中的ObjectWaiter對象放入到_EntryList中

關於放入到_EntryList的策略大概有4中Policy,其中還涉及到一個_cxq的隊列,先不具體介紹了

notify, 和notifyAll 都沒有釋放對象的鎖,而是在Synchronizer同步塊結束的時候釋放

如何釋放鎖

調用ObjectMonitor::exit

從_EntryList裡找到一個ObjectWaiter,因為ObjectWaiter裡有線程的_event ParkEvent,調用unpark() 通知ObjectWaite裡的線程運行(拿到鎖),具體實現在ObjectMonitor::ExitEpilog方法裡

Copyright © Linux教程網 All Rights Reserved