1)从java的视角看synchronized
synchronized使用的锁对象(monitor)存储在java对象头中。
monitor对象:
1)每个java对象都拥有一个Monitor锁(别问我为什么,虚拟机就是这样设计的)。
2)当一个monitor被持有后,它将处于锁定状态。
2)从C++源码看synchronized (参考:https://www.cnblogs.com/dennyzhangdd/p/6734638.html)
oopDesc ---> markOopDesc monitor()方法 --> ObjectMonitor 即 monitor -> monitor enter、monitor exit
1)openjdk\hotspot\src\share\vm\oops\oop.hpp下的oopDesc类是JVM对象的顶级基类,故每个object都包含markOop。
class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark; //标记字段(Mark Word)
union _metadata {
Klass* _klass; //对象类型元数据的指针
narrowKlass _compressed_klass;
} _metadata;
// Fast access to barrier set. Must be initialized.
static BarrierSet* _bs;
public:
markOop mark() const { return _mark; }
markOop* mark_addr() const { return (markOop*) &_mark; }
void set_mark(volatile markOop m) { _mark = m; }
void release_set_mark(markOop m);
markOop cas_set_mark(markOop new_mark, markOop old_mark);
// Used only to re-initialize the mark word (e.g., of promoted
// objects during a GC) -- requires a valid klass pointer
void init_mark();
Klass* klass() const;
Klass* klass_or_null() const volatile;
Klass** klass_addr();
narrowKlass* compressed_klass_addr();
....省略...
}
2)markOopDesc继承自oopDesc,并拓展了自己的方法monitor(),该方法返回一个ObjectMonitor*对象指针。
ObjectMonitor* monitor() const {
assert(has_monitor(), "check");
// Use xor instead of &~ to provide one extra tag-bit check.
return (ObjectMonitor*) (value() ^ monitor_value);
// -------------- 补充 ---------------------
// value()的实现: uintptr_t value() const { return (uintptr_t) this; }
//
// monitor_value的实现:
// enum {
// locked_value = 0,//00偏向锁
// unlocked_value = 1,//01无锁
// monitor_value = 2,//10监视器锁,又叫重量级锁
// marked_value = 3,//11GC标记
// biased_lock_pattern = 5 //101偏向锁
// };
// -------------- 补充 ---------------------
}
3)在HotSpot虚拟机中,采用ObjectMonitor类来实现monitor。
openjdk\hotspot\src\share\vm\runtime\objectMonitor.hpp源码如下:
ObjectMonitor() {
_header = NULL;//markOop对象头
_count = 0;
_waiters = 0,//等待线程数
_recursions = 0;//重入次数
_object = NULL;
_owner = NULL;//指向获得ObjectMonitor对象的线程或基础锁
_WaitSet = NULL;//处于wait状态的线程,会被加入到wait set;
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ;//处于等待锁block状态的线程,会被加入到entry set;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;// _owner is (Thread *) vs SP/BasicLock
_previous_owner_tid = 0;// 监视器前一个拥有者线程的ID
}