Java 使用 wait 等待会使 synchronized 升级为重量级锁
Java juc 锁 About 2,764 words原因
因为wait
方法会让锁对象从owner
拥有者变为waitSet
队列中等待。
所以必须关联一个Monitor
对象,这样synchronized
就升级为了重量级锁。
底层 C++ 代码
主要为ObjectMonitor
相关代码
class ObjectWaiter : public StackObj {
public:
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
enum Sorted { PREPEND, APPEND, SORTED } ;
ObjectWaiter * volatile _next;
ObjectWaiter * volatile _prev;
Thread* _thread;
jlong _notifier_tid;
};
class ObjectMonitor {
// ...
ObjectMonitor() {
_owner = NULL; // 锁持有者
_WaitSet = NULL; // 调用 wait 方法等待 notify 的列表
_WaitSetLock = 0 ;
_EntryList = NULL ; // 竞争锁的队列
_previous_owner_tid = 0;
}
};
wait
方法添加到waitSet
的双向链表中
// -----------------------------------------------------------------------------
// Wait/Notify/NotifyAll
//
// Note: a subset of changes to ObjectMonitor::wait()
// will need to be replicated in complete_exit above
void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
// ...
// create a node to be put into the queue
// Critically, after we reset() the event but prior to park(), we must check
// for a pending interrupt.
ObjectWaiter node(Self); // 包装成 waitSet 入队对象
node.TState = ObjectWaiter::TS_WAIT ;
Self->_ParkEvent->reset() ;
OrderAccess::fence(); // ST into Event; membar ; LD interrupted-flag
// Enter the waiting queue, which is a circular doubly linked list in this case
// but it could be a priority queue or any data structure.
// _WaitSetLock protects the wait queue. Normally the wait queue is accessed only
// by the the owner of the monitor *except* in the case where park()
// returns because of a timeout of interrupt. Contention is exceptionally rare
// so we use a simple spin-lock instead of a heavier-weight blocking lock.
// 自旋锁代替重量级锁
Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ; // 线程自旋
AddWaiter (&node) ; // waitSet 入队
Thread::SpinRelease (&_WaitSetLock) ;
}
// 添加到 waitSet 双向链表中
inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
assert(node != NULL, "should not dequeue NULL node");
assert(node->_prev == NULL, "node already in list");
assert(node->_next == NULL, "node already in list");
// put node at end of queue (circular doubly linked list)
// 双向链表
if (_WaitSet == NULL) {
_WaitSet = node;
node->_prev = node;
node->_next = node;
} else {
ObjectWaiter* head = _WaitSet ;
ObjectWaiter* tail = head->_prev;
assert(tail->_next == head, "invariant check");
tail->_next = node;
head->_prev = node;
node->_next = head;
node->_prev = tail;
}
}
OpenJDK 源码
Views: 2,684 · Posted: 2021-09-02
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...