用户空间锁-3-虚拟机锁相关类定义
一、class LockWord
/* 定义在 art/runtime/lock_word.h 中的 namespace art 命名空间中 */ class LockWord { private: uint32_t value_; //锁字是私有的 public: enum SizeShiftsAndMasks : uint32_t { /* 用于编码state的位数,当前只是胖或瘦/解锁或哈希码。是32位的。#### */ kStateSize = 2, //bit31-bit30 kReadBarrierStateSize = 1, //bit28 kMarkBitStateSize = 1, //bit29 /* 用于对瘦锁所有者进行编码的位数 */ kThinLockOwnerSize = 16, //bit27-bit12 /* 剩余的位是递归锁计数, 值为 12 == 32 - 16 - 2 - 1 - 1 */ kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize - kReadBarrierStateSize - kMarkBitStateSize, //bit11-bit0 /* Thin lock的位,所有者位于最低位 */ kThinLockOwnerShift = 0, kThinLockOwnerMask = (1 << kThinLockOwnerSize) - 1, //值为 0xffff == (1<<16)-1 kThinLockOwnerMaskShifted = kThinLockOwnerMask << kThinLockOwnerShift, //值为 0xffff = 0xffff << 0 kThinLockMaxOwner = kThinLockOwnerMask, //值为 0xffff /* Count in higher bits. */ kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift, //值为 16 == 16 + 0 kThinLockCountMask = (1 << kThinLockCountSize) - 1, //值为 0xfff == (1 << 12) - 1 kThinLockMaxCount = kThinLockCountMask, //值为 0xfff kThinLockCountOne = 1 << kThinLockCountShift, // 值为 65536 = 1 << 16 == 0x10000 kThinLockCountMaskShifted = kThinLockCountMask << kThinLockCountShift, //值为 0xfff0000 == 0xfff << 16 /* State in the highest bits. */ kStateShift = kReadBarrierStateSize + kThinLockCountSize + kThinLockCountShift + kMarkBitStateSize, //值为 30 == 1 + 12 + 16 + 1 kStateMask = (1 << kStateSize) - 1, //值为 3 == (1 << 2) - 1 kStateMaskShifted = kStateMask << kStateShift, //值为 3 << 30 kStateThinOrUnlocked = 0, //Thin/Unlock状态位是0 kStateFat = 1, //Fat Lock状态位是1 kStateHash = 2, //Hash的状态位是2 kStateForwardingAddress = 3, //前向地址的状态位是3 kStateForwardingAddressShifted = kStateForwardingAddress << kStateShift, //值为 3 << 30 kStateForwardingAddressOverflow = (1 + kStateMask - kStateForwardingAddress) << kStateShift, //值为 1<<30 == (1 + 3 - 3) << 30 /* Read barrier bit. */ kReadBarrierStateShift = kThinLockCountSize + kThinLockCountShift, //值为 28 == 12 + 16 kReadBarrierStateMask = (1 << kReadBarrierStateSize) - 1, //值为 1 == (1 <<1 )-1 kReadBarrierStateMaskShifted = kReadBarrierStateMask << kReadBarrierStateShift, //值为 1<<28 == 1 << 28 kReadBarrierStateMaskShiftedToggled = ~kReadBarrierStateMaskShifted, //值为 ~(1<<28) /* Mark bit. */ /* 值为 29 == 1 + 28 */ kMarkBitStateShift = kReadBarrierStateSize + kReadBarrierStateShift, /* 值为 1 == (1 << 1) - 1 */ kMarkBitStateMask = (1 << kMarkBitStateSize) - 1, /* 值为 1<<29 == 1 << 29 */ kMarkBitStateMaskShifted = kMarkBitStateMask << kMarkBitStateShift, /* 值为 ~(1<<29) */ kMarkBitStateMaskShiftedToggled = ~kMarkBitStateMaskShifted, /* GC state is mark bit and read barrier state. #### */ /* 值为 2 == 1 + 1 */ kGCStateSize = kReadBarrierStateSize + kMarkBitStateSize, //怎么r和m加在一起就是GC状态位呢? /* 值为 28 */ kGCStateShift = kReadBarrierStateShift, /* 值为 3<<28 == (1<<28) | (1<<29) */ kGCStateMaskShifted = kReadBarrierStateMaskShifted | kMarkBitStateMaskShifted, /* 值为 ~(3<<28) */ kGCStateMaskShiftedToggled = ~kGCStateMaskShifted, /* 当状态为kHashCode时,非状态的所有位保存哈希码。注意 Object.hashCode() 具有硬编码的哈希代码布局 */ kHashShift = 0, kHashSize = 32 - kStateSize - kReadBarrierStateSize - kMarkBitStateSize, //值为 28 == 32 - 2 - 1 - 1 kHashMask = (1 << kHashSize) - 1, //值为 0xfffffff == (1<<28) - 1 kMaxHash = kHashMask, //值为 0xfffffff == (1<<28) - 1 /* Forwarding address shift. 转发地址偏移, 值为 3 */ kForwardingAddressShift = kObjectAlignmentShift, //runtime_globals.h 中将其定义为3 kMonitorIdShift = kHashShift, //值为 0 kMonitorIdSize = kHashSize, //值为 28 kMonitorIdMask = kHashMask, //值为 0xfffffff == (1<<28) - 1 kMonitorIdAlignmentShift = 32 - kMonitorIdSize, //值为 4 == 32 - 28 kMonitorIdAlignment = 1 << kMonitorIdAlignmentShift, //值为 16 == 1 << 4 kMaxMonitorId = kMaxHash //值为 0xfffffff == (1<<28) - 1 }; public: static LockWord FromThinLockId(uint32_t thread_id, uint32_t count, uint32_t gc_state); //根据参数构造一个Thin lock类型的 LockWord 对象 static LockWord FromForwardingAddress(size_t target); static LockWord FromHashCode(uint32_t hash_code, uint32_t gc_state); static LockWord FromDefault(uint32_t gc_state); static bool IsDefault(LockWord lw); static LockWord Default(); LockState GetState(); //此函数获取当前锁的状态, kUnlocked、kThinLocked、kFatLocked、kHashCode、kForwardingAddress。 uint32_t ReadBarrierState(); //返回r位 uint32_t GCState(); //同时返回r位和m位 void SetReadBarrierState(uint32_t rb_state); uint32_t MarkBitState(); void SetMarkBitState(uint32_t mark_bit); uint32_t ThinLockOwner(); //返回owner thin lock的thread id uint32_t ThinLockCount(); //返回lock value被锁定的次数 Monitor* FatLockMonitor(); //返回被编码为fat lock的monitor size_t ForwardingAddress(); //返回存储在Monitor中的前向地址 LockWord(Monitor* mon, uint32_t gc_state); //构造一个用于膨胀的锁字,用来使用monitor. int32_t GetHashCode(); //返回存储在锁字中的hash code, 必须是kHashCode state static bool Equal(LockWord lw1, LockWord lw2); void Dump(std::ostream& os); //16进制打印锁字 value_ 的值 private: LockWord(); explicit LockWord(uint32_t val) : value_(val); void CheckReadBarrierState(); uint32_t GetValue(); //返回锁字 value_ 的值 uint32_t GetValueWithoutGCState(); }
锁值本身存储在 mirror::Object::monitor_ 中####。其中两个最高有效位编码了状态。四种可能的状态分别是:胖锁定(fat locked)、瘦/解锁(thin/unlocked)、哈希码(hash code)和转发地址(forwarding address)。
(1) 当锁字处于“thin”状态时,state 占2位 bit31-bit30, m 占1位 bit29, r 占1位 bit28, Owner 占16位 bit27-bit12, 递归计数占12位 bit11-bit0,,
其位格式如下:
|33|2|2|222222221111|1111110000000000|
|10|9|8|765432109876|5432109876543210|
|00|m|r| lock count |thread id owner |
(2) 当锁字处于“fat”状态时,其位格式如下:
|33|2|2|2222222211111111110000000000|
|10|9|8|7654321098765432109876543210|
|01|m|r| MonitorId |
(3) 当锁字处于哈希状态时,其位格式如下:
|33|2|2|2222222211111111110000000000|
|10|9|8|7654321098765432109876543210|
|10|m|r| HashCode |
(4) 当锁字处于转发地址状态时,state 占2位 bit31-bit30, m 占1位 bit29, r占1位 bit28, Hash占28位 bit27-bit0, 其位格式如下:
|33|2|22222222211111111110000000000|
|10|9|87654321098765432109876543210|
|11|0| ForwardingAddress |
`r` 位存储读取屏障状态。
`m` 位存储标记位状态。
注: 前一篇BK比这里注释的好。
二、class Thread
/* 位于 art/runtime/thread.h 中,定义在 namespace art 命名空间下 */ class Thread { /* 公有成员变量 */ public: static const size_t kStackOverflowImplicitCheckSize; static constexpr bool kVerifyStack = kIsDebugBuild; /* 私有成员变量 */ private: union StateAndFlags { struct{ volatile uint16_t flags; volatile uint16_t state; } as_struct; AtomicInteger as_atomic_int; volatile int32_t as_int; } static constexpr uint32_t kMaxSuspendBarriers = 3; //suspend屏障的最大数量。 static bool is_started_; //表示 Thread::Startup 是否被调用过 static pthread_key_t pthread_key_self_; //用于检索Thread*的 TLS 密钥 static ConditionVariable* resume_cond_; //用于通知线程它们应该尝试resume,如果它们的挂起计数> 0,它们将再次挂起。 static bool (*is_sensitive_thread_hook_)(); static Thread* jit_sensitive_thread_; /* 线程本地存储. */ struct tls_32bit_sized_values { union StateAndFlags state_and_flags; int suspend_count; //非零值用于告诉当前线程在下一次轮询时进入安全点。 int debug_suspend_count; // uint32_t thin_lock_thread_id; //见注释[1] uint32_t tid; //系统thread id #### const bool32_t daemon; //表示此线程是否是个daemon,typedef uint32_t bool32_t; bool32_t throwing_OutOfMemoryError; //是否递归地抛出 OOME。 uint32_t no_thread_suspension; //正值表示我们处于预计不会发生线程暂停的区域。 uint32_t thread_exit_check_count; //我们的 pthread 键的析构函数被调用了多少次? bool32_t handling_signal_; //如果信号正在由此线程处理,则为 True。 /* 如果线程处于 TransitionFromSuspendedToRunnable() 状态,则为 True。此属性用于区分即将转换为可运行 * 状态的非可运行线程(例如 kNative、kWaiting)。 */ bool32_t is_transitioning_to_runnable; bool32_t ready_for_debug_invoke; /* 如果线程已被调试器事件挂起,则为 True。此方法用于从调试器调用方法,该方法仅在线程被事件挂起时才允许 */ bool32_t ready_for_debug_invoke; bool32_t debug_method_entry_; //如果线程进入某个方法,则为 True。这用于检测调试器的方法进入事件 /* 如果 GC 处于标记阶段,则为 True。这仅适用于 CC 收集器。此操作是线程本地的,以便我们简化检查 GC 根读屏障快速路径的逻辑 */ bool32_t is_gc_marking; Atomic<bool32_t> interrupted; //线程“中断”状态;保持引发状态直到被查询或抛出。 AtomicInteger park_state_; /* 如果允许线程访问弱引用(Reference::GetReferent() 和系统弱引用),并可能将对象标记为活动/灰色,则为 True。 */ bool32_t weak_ref_access_enabled; /* Heap::disable_thread_flip_count_ 的线程本地版本。它会跟踪线程处于多少层(嵌套的)JNI 临界区,并用于检 * 测嵌套 JNI 临界区的进入。 */ uint32_t disable_thread_flip_count; /* suspend_count_ 中有多少是由用户代码请求的,用于区分由运行时挂起的线程和由用户代码挂起的线程 */ int user_code_suspend_count; /* 此线程被强制解释的次数。如果不为 0,则线程必须尽可能长时间地停留在解释代码中。 */ uint32_t force_interpreter_count; /* 如果一切处于快速解释的理想状态,则为 True。如果需要切换到 C++ 解释器来处理特殊情况,则为 False。 */ std::atomic<bool32_t> use_mterp; } tls32_; struct tls_64bit_sized_values { uint64_t trace_clock_base; //用于trace的clock base RuntimeStats stats; } tls64_; struct tls_ptr_sized_values { uint8_t* card_table; mirror::Throwable* exception; //待处理的异常或为空。 uint8_t* stack_end; //此线程堆栈的末尾 ManagedStack managed_stack; uintptr_t* suspend_trigger; JNIEnvExt* jni_env; //每个线程可能有一个关联的 JNI 环境 JNIEnvExt* tmp_jni_env; Thread* self; //初始化为“this”, 见注释[2]。 #### mirror::Object* opeer; jobject jpeer; uint8_t* stack_begin; //堆栈的“最低可寻址字节” size_t stack_size; //堆栈的大小 union DepsOrStackTraceSample { std::vector<ArtMethod*>* stack_trace_sample; //指向采样分析器捕获的先前堆栈跟踪的指针。 verifier::VerifierDeps* verifier_deps; } deps_or_stack_trace_sample; Thread* wait_next; //此线程属于等待集中的下一个线程 mirror::Object* monitor_enter_object; ////如果我们在 MonitorEnter 中被阻塞,这就是我们试图锁定的对象。#### BaseHandleScope* top_handle_scope; jobject class_loader_override; Context* long_jump_context; //线程本地、延迟分配、长跳转上下文。用于传递异常。 std::deque<instrumentation::InstrumentationStackFrame>* instrumentation_stack; //方法检测使用的额外堆栈,用于存储方法和返回 pc 值。 DebugInvokeReq* debug_invoke_req; //JDWP 断点调用支持 SingleStepControl* single_step_control; StackedShadowFrameRecord* stacked_shadow_frame_record; DeoptimizationContextRecord* deoptimization_context_stack; FrameIdToShadowFrame* frame_id_to_shadow_frame; std::string* name; //java.lang.Thread 名称的缓存副本。 #### pthread_t pthread_self; //此 Thread* 底层 pthread 的缓存 pthread_t。 const char* last_no_thread_suspension_cause; Closure* checkpoint_function; AtomicInteger* active_suspend_barriers[kMaxSuspendBarriers]; uint8_t* thread_local_start; //线程本地分配指针 #### uint8_t* thread_local_pos; uint8_t* thread_local_end; uint8_t* thread_local_limit; size_t thread_local_objects; JniEntryPoints jni_entrypoints; //入口点函数指针 QuickEntryPoints quick_entrypoints; void* mterp_current_ibase; //Mterp 跳转表基址。 void* rosalloc_runs[kNumRosAllocThreadLocalSizeBracketsInThread]; //16 StackReference<mirror::Object>* thread_local_alloc_stack_top; StackReference<mirror::Object>* thread_local_alloc_stack_end; BaseMutex* held_mutexes[kLockLevelCount]; Closure* flip_function; verifier::MethodVerifier* method_verifier; gc::accounting::AtomicStack<mirror::Object>* thread_local_mark_stack; mirror::Throwable* async_exception; } tlsPtr_; InterpreterCache interpreter_cache_; //解释器使用的小型线程本地缓存。它由 dex 指令指针作为键。其值取决于操作码(例如,字段偏移量)。 Mutex* wait_mutex_; //守护“wait_monitor_”成员。 ConditionVariable* wait_cond_; //等待期间等待的条件变量。 Monitor* wait_monitor_; //指向我们当前正在等待的monitor锁的指针 uint8_t debug_disallow_read_barrier_ = 0; uintptr_t poison_object_cookie_ = 0; std::list<Closure*> checkpoint_overflow_; SafeMap<std::string, std::unique_ptr<TLSData>> custom_tls_; bool is_runtime_thread_; //如果线程是某种形式的运行时线程(例如,GC 或 JIT),则为真。 /* 公有成员函数 */ public: /* 创建与指定托管对等体对应的新本机线程。用于实现 Thread.start。 */ static void CreateNativeThread(JNIEnv* env, jobject peer, size_t stack_size, bool daemon); /* 将调用的原生线程附加到runtime,并返回新的本地对等体。用于实现 JNI 的 AttachCurrentThread 和 AttachCurrentThreadAsDaemon 调用 */ static Thread* Attach(const char* thread_name, bool as_daemon, jobject thread_group, bool create_peer); /* 将调用本机线程附加到runtime,返回新的本地对等体。 */ static Thread* Attach(const char* thread_name, bool as_daemon, jobject thread_peer); void InitAfterFork(); //fork后重置子线程的内部状态。 /* 获取当前正在执行的线程,通常称为“self”。此调用的成本相当高,因此我们建议尽可能传递 self */ static Thread* Current(); void AllowThreadSuspension(); void CheckSuspend(); void CheckEmptyCheckpointFromWeakRefAccess(BaseMutex* cond_var_mutex); void CheckEmptyCheckpointFromMutex(); static Thread* FromManagedThread(const ScopedObjectAccessAlreadyRunnable& ts, ObjPtr<mirror::Object> thread_peer); static Thread* FromManagedThread(const ScopedObjectAccessAlreadyRunnable& ts, jobject thread); static void DumpThreadOffset(std::ostream& os, uint32_t offset); void ShortDump(std::ostream& os); //dump一行线程状态摘要 /* dump详细的线程状态和stack */ void Dump(std::ostream& os, bool dump_native_stack = true, BacktraceMap* backtrace_map = nullptr, bool force_dump_stack = false); void DumpJavaStack(std::ostream& os, bool check_suspended = true, bool dump_locks = true); static void DumpState(std::ostream& os, const Thread* thread, pid_t tid); //dump每个线程的 SIGQUIT 标头。 ThreadState GetState(); //返回成员 tls32_.state_and_flags.as_struct.state ThreadState SetState(ThreadState new_state); int GetSuspendCount(); //返回 tls32_.suspend_count; int GetUserCodeSuspendCount(); //返回 tls32_.user_code_suspend_count int GetDebugSuspendCount(); //返回 tls32_.debug_suspend_count bool IsSuspended(); bool ModifySuspendCount(Thread* self, int delta, AtomicInteger* suspend_barrier, SuspendReason reason); ... bool IsDaemon(); //返回 tls32_.daemon /* 更改此线程的优先级,使其与 java.lang.Thread 对象的优先级匹配。将优先级值从1到10映射到 Linux 的“nice”值,其中数字越小,优先级越高 */ void SetNativePriority(int newPriority); //Java层的优先级 #### int GetNativePriority(); uint32_t GetThreadId(); //返回 tls32_.thin_lock_thread_id; pid_t GetTid(); //返回 tls32_.tid, 这个是底层的线程tid, 已经封装好了函数。#### ObjPtr<mirror::String> GetThreadName(); //返回 java.lang.Thread() 的名称,如果此 Thread* 没有对等体,则返回 null。 void GetThreadName(std::string& name); void SetThreadName(const char* name) REQUIRES_SHARED(Locks::mutator_lock_); //设置线程名 uint64_t GetCpuMicroTime(); //返回线程特定的 CPU 时间时钟 mirror::Object* GetPeer(); //返回对等体 tlsPtr_.opeer mirror::Object* GetPeerFromOtherThread(); bool HasPeer(); RuntimeStats* GetStats(); //返回 tls64_.stats bool IsStillStarting(); bool IsExceptionPending(); bool IsAsyncExceptionPending(); mirror::Throwable* GetException(); void SetException(ObjPtr<mirror::Throwable> new_exception); //设置从其他线程异步抛出的异常。 void ClearException(); //就是将 tlsPtr_.exception = nullptr bool ObserveAsyncException(); //将当前的异步异常移至主异常 void QuickDeliverException(); //找到 catch 块并执行长跳转到适当的异常句柄 Context* GetLongJumpContext(); void ReleaseLongJumpContext(Context* context); //将 tlsPtr_.long_jump_context = context; ArtMethod* GetCurrentMethod(uint32_t* dex_pc, bool check_suspended = true, bool abort_on_error = true); //获取当前方法和 dex pc bool IsExceptionThrownByCurrentMethod(ObjPtr<mirror::Throwable> exception); //判断异常是不是被当前正在执行的Java方法抛出的 static void Startup(); static void FinishStartup(); static void Shutdown(); void NotifyThreadGroup(ScopedObjectAccessAlreadyRunnable& soa, jobject thread_group = nullptr); //告诉此线程的线程组它已启动 JNIEnvExt* GetJniEnv(); //JNI方法集 #### ObjPtr<mirror::Object> DecodeJObject(jobject obj); //将一个jobject转换为Object*指针 mirror::Object* GetMonitorEnterObject(); //返回 tlsPtr_.monitor_enter_object void SetMonitorEnterObject(mirror::Object* obj); //tlsPtr_.monitor_enter_object = obj; bool Interrupted(); //实现 java.lang.Thread.interrupted. bool IsInterrupted(); //实现 java.lang.Thread.isInterrupted. void Interrupt(Thread* self); void SetInterrupted(bool i); void Notify(); void PoisonObjectPointers(); //++poison_object_cookie_ uintptr_t GetPoisonObjectCookie(); //返回 poison_object_cookie_ void Park(bool is_absolute, int64_t time) REQUIRES_SHARED(Locks::mutator_lock_); void Unpark(); Mutex* GetWaitMutex(); //返回 wait_mutex_ ConditionVariable* GetWaitConditionVariable(); //返回 wait_cond_ Monitor* GetWaitMonitor(); //返回 wait_monitor_ void SetWaitMonitor(Monitor* mon); //设置成员 wait_monitor_ Thread* GetWaitNext(); //返回 tlsPtr_.wait_next void SetWaitNext(Thread* next); //设置 tlsPtr_.wait_next jobject GetClassLoaderOverride(); //返回 tlsPtr_.class_loader_override void SetClassLoaderOverride(jobject class_loader_override); /* 创建堆栈跟踪的内部表示,与 StackTraceElement[] 相比,其计算时间和空间效率更高 */ jobject CreateInternalStackTrace(const ScopedObjectAccessAlreadyRunnable& soa); /* 将内部堆栈跟踪表示(由 CreateInternalStackTrace 返回)转换为 StackTraceElement[] */ static jobjectArray InternalStackTraceToStackTraceElementArray(const ScopedObjectAccessAlreadyRunnable& soa, jobject internal, ...); jobjectArray CreateAnnotatedStackTrace(const ScopedObjectAccessAlreadyRunnable& soa); bool HasDebuggerShadowFrames(); ... static constexpr ThreadOffset<pointer_size> ThinLockIdOffset(); //Thin Lock有关 static constexpr ThreadOffset<pointer_size> InterruptedOffset(); static constexpr ThreadOffset<pointer_size> ThreadFlagsOffset(); static constexpr ThreadOffset<pointer_size> UseMterpOffset(); static constexpr ThreadOffset<pointer_size> IsGcMarkingOffset(); static constexpr size_t IsGcMarkingSize(); //返回 tls32_.is_gc_marking void DeoptimizeWithDeoptimizationException(JValue* result); ... size_t GetStackSize(); //返回 tlsPtr_.stack_size - (tlsPtr_.stack_end - tlsPtr_.stack_begin) bool GetIsGcMarking(); //返回 tls32_.is_gc_marking bool IsRuntimeThread(); bool ReadFlag(ThreadFlag flag); ... bool HandlingSignal(); //返回 tls32_.handling_signal_ TLSData* GetCustomTLS(const char* key); //获取与该key关联的当前 TLSData void SetCustomTLS(const char* key, TLSData* data); //将“key”处的 tls 条目设置为 data。 /* 私有成员函数 */ private: static constexpr ThreadOffset<pointer_size> ThreadOffsetFromTlsPtr(size_t tls_ptr_offset); explicit Thread(bool daemon); ~Thread(); //析构函数是私有的 void Destroy(); static Thread* Attach(const char* thread_name, bool as_daemon, PeerAction p); //将调用的本地线程附加到运行时,并返回新的原生对等体 bool Init(ThreadList*, JavaVMExt*, JNIEnvExt* jni_env_ext = nullptr); //初始化线程 void InitCpu(); void CleanupCpu(); void InitTid(); };
注释[1]:
thin_lock_thread_id 成员变量是瘦锁线程 ID。这是一个由瘦锁实现使用的较小整数。请勿将其与原生线程的 tid 混淆,它也不是 java.lang.Thread.getId() 返回的值 —— 它是一个独立的值,仅用于锁定。此 ID 与托管代码可见的 ID 之间的一个重要区别是,托管代码可见的 ID 会被重用(以确保它们符合可用的位数)。
注释[2]:
Thread* self 成员被初始化为“this”。在某些架构(例如 x86)上,读取 Thread::Current 很容易,但获取 Thread::Current 的地址却很困难。可以通过读取 Thread::Current 的此字段来获取地址。
三、class Monitor
/* 位于 art/runtime/monitor.h 中,定义在 namespace art 命名空间下 */ class Monitor { /* 公有成员变量: */ public: /* 线程挂起前默认的自旋次数,用于强制扩充锁字。请参阅 Runtime::max_spins_before_thin_lock_inflation_ */ constexpr static size_t kDefaultMaxSpinsBeforeThinLockInflation = 50; /* 私有成员变量: */ private: static uint32_t lock_profiling_threshold_; static uint32_t stack_dump_lock_profiling_threshold_; Mutex monitor_lock_; //见注释[2] ConditionVariable monitor_contenders_; size_t num_waiters_; //等待在条件变量上的waiters的个数 Thread* volatile owner_; //见注释[3],持锁的owner,即当前持有锁的线程 int lock_count_; //Owner递归持锁的深度,monitor锁支持重入。#### GcRoot<mirror::Object> obj_; //该monitor对应的Object,是个弱根,只能通过GetObject()访问。 Thread* wait_set_; //当前正在等待这个monitor的线程集合。 Thread* wake_set_; //当前正在竞争获取此monitor(监视器)的线程集合。 AtomicInteger hash_code_; //用于存储对象的hash code,由 GetHashCode() 延迟生成 /* 锁拥有者获取锁的方法和 dex pc,当启用锁采样时使用。如果锁当前未锁定,或者当堆栈为空时获取锁,locking_method_ 可能为空 */ ArtMethod* locking_method_; uint32_t locking_dex_pc_; MonitorId monitor_id_; //存储在锁字中的此监视器的更密集编码版本 /* 公有成员函数: */ public: ~Monitor(); //析构公有 static void Init(uint32_t lock_profiling_threshold, uint32_t stack_dump_lock_profiling_threshold); //初始化是静态的(全局唯一的) static uint32_t GetLockOwnerThreadId(ObjPtr<mirror::Object> obj); //静态的 static ObjPtr<mirror::Object> MonitorEnter(Thread* thread, ObjPtr<mirror::Object> obj, bool trylock); //静态的 #### static bool MonitorExit(Thread* thread, ObjPtr<mirror::Object> obj); //静态的 #### static void Notify(Thread* self, ObjPtr<mirror::Object> obj); static void NotifyAll(Thread* self, ObjPtr<mirror::Object> obj); static void Wait(Thread* self, ObjPtr<mirror::Object> obj, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why); static ThreadState FetchState(const Thread* thread, /*out*/ ObjPtr<mirror::Object>* monitor_object, /*out*/ uint32_t* lock_owner_tid); static ObjPtr<mirror::Object> GetContendedMonitor(Thread* thread); static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(ObjPtr<mirror::Object>, void*), void* callback_context, bool abort_on_failure = true); static bool IsValidLockWord(LockWord lock_word); ObjPtr<mirror::Object> GetObject(); void SetObject(ObjPtr<mirror::Object> object); Thread* GetOwner(); //返回成员变量 owner_ int32_t GetHashCode(); bool IsLocked(); bool HasHashCode(); MonitorId GetMonitorId(); //返回成员变量 monitor_id_ static void InflateThinLocked(Thread* self, Handle<mirror::Object> obj, LockWord lock_word, uint32_t hash_code); static bool Deflate(Thread* self, ObjPtr<mirror::Object> obj); /* 私有成员函数: */ private: Monitor(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code); //私有的构造函数 Monitor(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code, MonitorId id); //私有的构造函数 /* 将 monitor 安装到其 object 中,如果另一个线程首先安装了不同的monitor,则可能会失败 */ bool Install(Thread* self); /* 将线程链接到monitor的等待集。此例程的调用者必须持有monitor lock */ void AppendToWaitSet(Thread* thread) REQUIRES(monitor_lock_); /* 将线程从监视器的等待集解除链接。monitor lock必须由此例程的调用者持有 */ void RemoveFromWaitSet(Thread* thread) REQUIRES(monitor_lock_); void SignalContendersAndReleaseMonitorLock(Thread* self); static void Inflate(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code); void LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, ArtMethod* owner_method, uint32_t owner_dex_pc); static void FailedUnlock(ObjPtr<mirror::Object> obj, uint32_t expected_owner_thread_id, uint32_t found_owner_thread_id, Monitor* mon); /* 尝试不阻塞持锁,如果成功持锁返回true */ bool TryLock(Thread* self); bool TryLockLocked(Thread* self); void Lock(Thread* self); bool Unlock(Thread* thread); static void DoNotify(Thread* self, ObjPtr<mirror::Object> obj, bool notify_all); void Notify(Thread* self); void NotifyAll(Thread* self); static std::string PrettyContentionInfo(const std::string& owner_name, pid_t owner_tid, ArtMethod* owners_method, uint32_t owners_dex_pc, size_t num_waiters); void Wait(Thread* self, int64_t msec, int32_t nsec, bool interruptShouldThrow, ThreadState why); //见注释[1] /* 将提供的方法和 pc 转换为其声明类的源文件和行号。 */ static void TranslateLocation(ArtMethod* method, uint32_t pc, const char** source_file, int32_t* line_number); uint32_t GetOwnerThreadId(); /* 支持监控操作的 systrace 输出。 */ static void AtraceMonitorLock(Thread* self, ObjPtr<mirror::Object> obj, bool is_wait); static void AtraceMonitorLockImpl(Thread* self, ObjPtr<mirror::Object> obj, bool is_wait); static void AtraceMonitorUnlock(); }
注释[1]:
在监视器上等待,直到超时、中断或收到通知。用于 Object.wait() 以及(某种程度上间接地) Thread.sleep() 和 Thread.join()。如果另一个线程调用 Thread.interrupt(),我们会抛出 InterruptedException 异常,并在以下情况之一成立时立即返回:
- 在 Object 的 wait()、wait(long) 或 wait(long, int) 方法中阻塞.
- 在 Thread 的 join()、join(long) 或 join(long, int) 方法中阻塞.
- 在 Thread 的 sleep(long) 或 sleep(long, int) 方法中阻塞.
否则,我们会设置“interrupted”标志。
检查以确保“ns”在 0-999999 范围内(即毫秒的几分之一),如果不是,则抛出相应的异常。
规范允许“虚假唤醒(spurious wakeups)”,并建议所有使用 Object.wait() 的代码都循环执行此操作。这似乎源于人们对多处理器系统上 pthread_cond_wait() 的担忧。网络上的一些评论对这些是否能够/应该发生表示怀疑。
由于我们被允许“提前”唤醒,因此我们限制了极长的持续时间,使其在 32 位时间纪元结束时返回。
注释[2]:
有博客说Monitor底层是通过mutex来实现同步控制的,此 monitor_lock_ 就是monitor进入mutex模块的桥梁,变成 fat lock之后,Monitor::MonitorEnter 将会调用 Monitor::Lock来持锁。
注释[3]:
owner_ 成员记录了谁是monitor的owner,即目前在临界区运行的是哪个线程。
三、class Mutex
全局变量:
constexpr bool kLogLockContentions = false; //若是想使能锁竞争log设置为true
constexpr int kWakeOne = 1;
constexpr int kWakeAll = INT_MAX;
1. class BaseMutex
先看下class BaseMutex, 它是所有Mutex实现的基类:
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class BaseMutex { /* 成员变量 */ protected: const char* const name_; //基类有名字,看来每个锁都是有名字的 /* 用于记录竞争的一个log条目 */ struct ContentionLogEntry { uint64_t blocked_tid; uint64_t owner_tid; AtomicInteger count; }; struct ContentionLogData { ContentionLogEntry contention_log[kContentionLogSize]; //4 AtomicInteger cur_content_log_entry; //争用日志中下一个要更新的条目, 0--kContentionLogSize-1。 AtomicInteger contention_count; //此Mutex被竞争的次数 Atomic<uint64_t> wait_time; //所有竞争者等待的时间总和(ns)。#### void AddToWaitTime(uint64_t value); }; ContentionLogData contention_log_data_[kContentionLogDataSize]; //0长度数组 const LockLevel level_; //支持锁层次结构。 bool should_respond_to_empty_checkpoint_request_; pubilc: const char* GetName(); //返回成员变量 name_ /* 带默认实现的纯虚函数,子类就没必要全部重载了,用于对外告知自己是哪类锁 */ virtual bool IsMutex() const { return false; } //加const表示常量成员函数,即承诺不修改对象成员变量,允许通过const成员调用 virtual bool IsReaderWriterMutex() const { return false; } virtual bool IsMutatorMutex() const { return false; } virtual void Dump(std::ostream& os) const = 0; //每个子类必须实现 static void DumpAll(std::ostream& os); bool ShouldRespondToEmptyCheckpointRequest(); //直接返回成员变量 should_respond_to_empty_checkpoint_request_ void SetShouldRespondToEmptyCheckpointRequest(bool value); //设置成员变量 should_respond_to_empty_checkpoint_request_ /* 不带默认实现的纯虚函数,子类必须重载 */ virtual void WakeupToRespondToEmptyCheckpoint() = 0; bool HasEverContended(); protected: BaseMutex(const char* name, LockLevel level); virtual ~BaseMutex(); void RegisterAsLocked(Thread* self); void RegisterAsUnlocked(Thread* self); void CheckSafeToWait(Thread* self); void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t nano_time_blocked); void DumpContention(std::ostream& os) const; }
2. class Mutex
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class Mutex : public BaseMutex { /* 成员变量全是private的 */ private: AtomicInteger state_and_contenders_; //futex()中传的锁字,低位 0:未持锁,1持锁,高位是竞争者正处理等待的个数 static constexpr int32_t kHeldMask = 1; static constexpr int32_t kContenderShift = 1; static constexpr int32_t kContenderIncrement = 1 << kContenderShift; //1<<1=2 Atomic<pid_t> exclusive_owner_; //独占Owner的tid #### unsigned int recursion_count_; //重入嵌套持锁的深度 const bool recursive_; //表示此锁是否可以重入持有 #### public: explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false); ~Mutex(); bool IsMutex() override { return true; }; //恒返回true void ExclusiveLock(Thread* self); //阻塞直到互斥锁空闲然后获取独占访问权限。应该是独占锁实现。#### void Lock(Thread* self) { ExclusiveLock(self); } //默认实现是独占锁 bool ExclusiveTryLock(Thread* self); //成功获取独占锁返回true,否则返回false. bool TryLock(Thread* self) { return ExclusiveTryLock(self); } void ExclusiveUnlock(Thread* self); //释放独占锁 void Unlock(Thread* self) { ExclusiveUnlock(self); } bool IsExclusiveHeld(const Thread* self); //当前线程是否是独占 Mutex 锁的持有者。 void AssertExclusiveHeld(const Thread* self); //断言互斥锁被当前线程持有 void AssertHeld(const Thread* self); oid AssertNotHeldExclusive(const Thread* self); //断言互斥锁没有被当前线程持有 void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); } pid_t GetExclusiveOwnerTid(); //独占Owner的tid.#### ###### 这个是tid,已经有了持锁owner的tid ===== unsigned int GetDepth(); //获取重入深度,返回成员变量 recursion_count_ void Dump(std::ostream& os); //基类定义的,必须重载 const Mutex& operator!() const { return *this; } //对于 clang 注释中的负面能力。 void WakeupToRespondToEmptyCheckpoint(); //唤醒所有等待者 private: increment_contenders(); //对成员变量 state_and_contenders_ += kContenderIncrement, 即加2,应该是bit0有特殊用途 void decrement_contenders(); //对成员变量 state_and_contenders_ -= kContenderIncrement, 即减2,应该是bit0有特殊用途 int32_t get_contenders(); //返回 state_and_contenders_ >> 1 返回竞争等待者的个数 }
Mutex用于实现线程间的互斥。互斥锁可用于获取对其所保护对象的独占访问权限。互斥锁可以处于以下两种状态之一:
- Free - 不属于任何线程;
- Exclusive - 仅由单个线程拥有。
锁定和解锁操作对状态的影响如下:
-------------------------------------------- State | ExclusiveLock | ExclusiveUnlock -------------------------------------------- Free | Exclusive | error Exclusive | Block* | Free --------------------------------------------
*互斥锁不可重入,因此在同一线程上尝试独占锁定将导致错误。不可重入简化了等待条件变量的过程。
3. class ReaderWriterMutex
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class ReaderWriterMutex : public BaseMutex { /* 成员变量都是私有的 */ private: AtomicInteger state_; //-1 表示独占持有,+ve 表示由多名所有者共享持有。 Atomic<pid_t> exclusive_owner_; //独占持锁的Owner的tid #### AtomicInteger num_pending_readers_; //等待获取读锁的竞争者的个数 AtomicInteger num_pending_writers_; //等待获取写锁的竞争者的个数 public: explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel); //explicit防止隐式调用 ~ReaderWriterMutex(); bool IsReaderWriterMutex() override { return true; } //恒返回true 表示自己是RWL void ExclusiveLock(Thread* self); //独占获取锁,阻塞直到锁空闲然后获取独占访问权限。 void WriterLock(Thread* self) { ExclusiveLock(self); } //写获取锁就是独占获取锁 void ExclusiveUnlock(Thread* self); //释放独占获取 void WriterUnlock(Thread* self) { ExclusiveUnlock(self); } //写释放就是释放独占获取 /* 阻塞直到 ReaderWriterMutex 空闲并获得独占访问权限。成功则返回 true,超时则返回 false。 */ bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns); /* 阻塞直到锁被共享或释放,然后获取访问的共享 */ void SharedLock(Thread* self); void ReaderLock(Thread* self) { SharedLock(self); } bool SharedTryLock(Thread* self); //尝试以共享方式获取锁 /* 释放共享锁 */ void SharedUnlock(Thread* self); void ReaderUnlock(Thread* self){ SharedUnlock(self); } bool IsExclusiveHeld(const Thread* self) const; //判断当前线程是否独占获取着锁 /* 断言当前线程具有独占访问权 */ void AssertExclusiveHeld(const Thread* self) const; void AssertWriterHeld(const Thread* self) const; /* 断言当前线程不具有独占访问权 */ void AssertNotExclusiveHeld(const Thread* self) void AssertNotWriterHeld(const Thread* self) bool IsSharedHeld(const Thread* self); //判断当前线程是否是共享持锁者 void AssertSharedHeld(const Thread* self); //断言当前线程具有共享访问权限。 void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); } void AssertNotHeld(const Thread* self); //断言当前线程未在共享或独占模式下持有此锁 pid_t GetExclusiveOwnerTid() const; //这个也是直接获取持锁Owner的tid的,若是多个读者共享则返回-1 #### void Dump(std::ostream& os) const override; const ReaderWriterMutex& operator!() const { return *this; } //对于 clang 注释中的负面能力。 void WakeupToRespondToEmptyCheckpoint() override; //读写锁的实现是唤醒所有的waiter private: void HandleSharedLockContention(Thread* self, int32_t cur_state); //处理 SharedLock 争用的外部路径 }
ReaderWriterMutex 用于实现线程间的互斥,类似于 Mutex。与 Mutex 不同的是,ReaderWriterMutex 可用于获取对其所守护对象的独占(写入)或共享(读取)访问权限。Mutex 的一个缺陷是它不能与条件变量一起使用。ReaderWriterMutex 可以处于以下三种状态之一:
- Free - 不属于任何线程,
- Exclusive - 仅由单个线程拥有,
- Shared(n) - 由 n 个线程共享。
锁定和解锁操作对状态的影响如下:
------------------------------------------------------------------------------------- State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock ------------------------------------------------------------------------------------- Free | Exclusive | error | SharedLock(1) | error Exclusive | Block | Free | Block | error Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free -------------------------------------------------------------------------------------
* 对于较大的 n 值,SharedLock 可能会阻塞。
4. class MutatorMutex
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class MutatorMutex : public ReaderWriterMutex { //是RWM的子类 public: explicit MutatorMutex(const char* name, LockLevel level = kDefaultMutexLevel) : ReaderWriterMutex(name, level) {} ~MutatorMutex() {} virtual bool IsMutatorMutex() const { return true; } const MutatorMutex& operator!() const { return *this; } //对于 clang 注释中的负面能力。 private: void TransitionFromRunnableToSuspended(Thread* self); void TransitionFromSuspendedToRunnable(Thread* self); };
MutatorMutex 是一种特殊的 ReaderWriterMutex,专门为 Locks::mutator_lock_ 互斥锁创建。其行为与 ReaderWriterMutex 相同,只是线程状态的变化也会影响锁的所有权。mutator_lock_ 不会被任何互斥锁线程真正持有。但是,处于 kRunnable 状态的线程被视为拥有互斥锁的共享所有权,因此 kRunnable 状态的进出转换会对锁所有权产生相关影响。接口中添加了处理状态转换的额外方法,但只有处理状态转换的方法才能访问。线程状态和标志属性用于确保线程状态转换与互斥锁的允许行为一致。
*) 此行为最重要的结果是,在寻求互斥锁的独占所有权之前,所有线程必须处于挂起状态之一。
5. class ConditionVariable
条件变量允许线程排队并休眠。之后,线程可以单独(Signal)或同时(Broadcast)恢复。
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class ConditionVariable { /* 成员变量全是private的 */ private: const char* const name_; Mutex& guard_; //等待者正在使用的互斥锁 /* 一个由信号和广播修改的计数器。这确保了当等待者放弃其互斥量,而另一个线程获取该互斥量并 * 发出信号时,等待线程会观察到 sequence_ 已更改,并且不会进入等待状态。在持有 guard_ 时会 * 进行修改,但会在不持有 guard_ 的情况下被 futex wait 读取。 */ AtomicInteger sequence_; public: ConditionVariable(const char* name, Mutex& mutex); ~ConditionVariable(); void Broadcast(Thread* self); //需要保持互斥。 void Signal(Thread* self); //需要保持互斥。 void Wait(Thread* self); bool TimedWait(Thread* self, int64_t ms, int32_t ns); void WaitHoldingLocks(Thread* self); void CheckSafeToWait(Thread* self); void SetCondOwner(int32_t owner_tid); //设置成员变量 cond_owner_ private: void RequeueWaiters(int32_t count); void SetCondOwner(int32_t owner_tid); }
6. class MutexLock
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class MutexLock { private: Thread* const self_; Mutex& mu_; public: /* 构造函数中持互斥锁,析构函数中释放互斥锁 */ MutexLock(Thread* self, Mutex& mu) : self_(self), mu_(mu) { mu_.ExclusiveLock(self_); } ~MutexLock() { mu_.ExclusiveUnlock(self_); } };
基于Mutex的实现。常规 Mutex 的作用域锁定器/解锁器,在构造时获取 mu,在销毁时释放它。
7. class ReaderMutexLock
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class ReaderMutexLock { private: Thread* const self_; ReaderWriterMutex& mu_; public: ReaderMutexLock(Thread* self, ReaderWriterMutex& mu); ~ReaderMutexLock(); };
基于 ReaderWriterMutex 的作用域锁定器/解锁器####,在构造时获取对 mu 的读取访问权限,并在销毁时释放它。
8. class WriterMutexLock
/* 定义在 art/runtime/base/mutex.h 中的 namespace art 命名空间中 */ class WriterMutexLock { private: Thread* const self_; ReaderWriterMutex& mu_; public: WriterMutexLock(Thread* self, ReaderWriterMutex& mu) : self_(self), mu_(mu) { mu_.ExclusiveLock(self_); } ~WriterMutexLock() { mu_.ExclusiveUnlock(self_); } };
基于 ReaderWriterMutex 的作用域锁定器/解锁器,在构造时获取对 mu 的写访问权限,并在销毁时释放它。
posted on 2025-05-04 18:41 Hello-World3 阅读(47) 评论(0) 收藏 举报
浙公网安备 33010602011771号