Java lock/unlock实现原理: Unsafe monitorEnter、monitorExit、tryMonitorEnter,这3个方法都有1个参数,表示要锁定的对象。对应的本机实现分别为Unsafe_MonitorEnter、Unsafe_MonitorExit、Unsafe_TryMonitorEnter。
monitorEnter方法定义如下:
/** Lock the object. It must get unlocked via {@link #monitorExit}. */
public native void monitorEnter(Object o);
tryMonitorEnter
方法定义如下:
/**
* Tries to lock the object. Returns true or false to indicate
* whether the lock succeeded. If it did, the object must be
* unlocked via {@link #monitorExit}.
*/
public native boolean tryMonitorEnter(Object o);
monitorExit方法定义如下:
/**
* Unlock the object. It must have been locked via {@link
* #monitorEnter}.
*/
public native void monitorExit(Object o);
Unsafe_MonitorEnter方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
UnsafeWrapper("Unsafe_MonitorEnter");
{
if (jobj == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
Handle obj(thread, JNIHandles::resolve_non_null(jobj));
ObjectSynchronizer::jni_enter(obj, CHECK);
}
UNSAFE_END
以上代码需要将宏展开,从代码上看,
void ATTR ObjectMonitor::enter(TRAPS) {
// The following code is ordered to check the most common cases first
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
Thread * const Self = THREAD ;
void * cur ;
cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
if (cur == NULL) {
// Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
assert (_recursions == 0 , "invariant") ;
assert (_owner == Self, "invariant") ;
// CONSIDER: set or assert OwnerIsThread == 1
return ;
}
if (cur == Self) {
// TODO-FIXME: check for integer overflow! BUGID 6557169.
_recursions ++ ;
return ;
}
if (Self->is_lock_owned ((address)cur)) {
assert (_recursions == 0, "internal state error");
_recursions = 1 ;
// Commute owner from a thread-specific on-stack BasicLockObject address to
// a full-fledged "Thread *".
_owner = Self ;
OwnerIsThread = 1 ;
return ;
}
// We've encountered genuine contention.
assert (Self->_Stalled == 0, "invariant") ;
Self->_Stalled = intptr_t(this) ;
// Try one round of spinning *before* enqueueing Self
// and before going through the awkward and expensive state
// transitions. The following spin is strictly optional ...
// Note that if we acquire the monitor from an initial spin
// we forgo posting JVMTI events and firing DTRACE probes.
if (Knob_SpinEarly && TrySpin (Self) > 0) {
assert (_owner == Self , "invariant") ;
assert (_recursions == 0 , "invariant") ;
assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
Self->_Stalled = 0 ;
return ;
}
assert (_owner != Self , "invariant") ;
assert (_succ != Self , "invariant") ;
assert (Self->is_Java_thread() , "invariant") ;
JavaThread * jt = (JavaThread *) Self ;
assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
assert (jt->thread_state() != _thread_blocked , "invariant") ;
assert (this->object() != NULL , "invariant") ;
assert (_count >= 0, "invariant") ;
// Prevent deflation at STW-time. See deflate_idle_monitors() and is_busy().
// Ensure the object-monitor relationship remains stable while there's contention.
Atomic::inc_ptr(&_count);
{ // Change java thread status to indicate blocked on monitor enter.
JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
if (JvmtiExport::should_post_monitor_contended_enter()) {
JvmtiExport::post_monitor_contended_enter(jt, this);
}
OSThreadContendState osts(Self->osthread());
ThreadBlockInVM tbivm(jt);
Self->set_current_pending_monitor(this);
// TODO-FIXME: change the following for(;;) loop to straight-line code.
for (;;) {
jt->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition()
// or java_suspend_self()
EnterI (THREAD) ;
if (!ExitSuspendEquivalent(jt)) break ;
//
// We have acquired the contended monitor, but while we were
// waiting another thread suspended us. We don't want to enter
// the monitor while suspended because that would surprise the
// thread that suspended us.
//
_recursions = 0 ;
_succ = NULL ;
exit (Self) ;
jt->java_suspend_self();
}
Self->set_current_pending_monitor(NULL);
}
Atomic::dec_ptr(&_count);
assert (_count >= 0, "invariant") ;
Self->_Stalled = 0 ;
// Must either set _recursions = 0 or ASSERT _recursions == 0.
assert (_recursions == 0 , "invariant") ;
assert (_owner == Self , "invariant") ;
assert (_succ != Self , "invariant") ;
assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
// The thread -- now the owner -- is back in vm mode.
// Report the glorious news via TI,DTrace and jvmstat.
// The probe effect is non-trivial. All the reportage occurs
// while we hold the monitor, increasing the length of the critical
// section. Amdahl's parallel speedup law comes vividly into play.
//
// Another option might be to aggregate the events (thread local or
// per-monitor aggregation) and defer reporting until a more opportune
// time -- such as next time some thread encounters contention but has
// yet to acquire the lock. While spinning that thread could
// spinning we could increment JVMStat counters, etc.
DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
if (JvmtiExport::should_post_monitor_contended_entered()) {
JvmtiExport::post_monitor_contended_entered(jt, this);
}
if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
ObjectMonitor::_sync_ContendedLockAttempts->inc() ;
}
}
Unsafe_TryMonitorEnter方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
UnsafeWrapper("Unsafe_TryMonitorEnter");
{
if (jobj == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
}
Handle obj(thread, JNIHandles::resolve_non_null(jobj));
bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
return (res ? JNI_TRUE : JNI_FALSE);
}
UNSAFE_END
bool ObjectMonitor::try_enter(Thread* THREAD) {
if (THREAD != _owner) {
if (THREAD->is_lock_owned ((address)_owner)) {
assert(_recursions == 0, "internal state error");
_owner = THREAD ;
_recursions = 1 ;
OwnerIsThread = 1 ;
return true;
}
if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
return false;
}
return true;
} else {
_recursions++;
return true;
}
}
Unsafe_MonitorExit方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
UnsafeWrapper("Unsafe_MonitorExit");
{
if (jobj == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
ObjectSynchronizer::jni_exit(obj(), CHECK);
}
UNSAFE_END
分享到:
相关推荐
在Java编程中,sun.misc.UnSafe类是一个非常特殊的存在。这个类在JDK8中扮演着一个核心的角色,它提供了对Java语言规范中未公开的底层操作的访问。尽管UnSafe类并非设计为公共API的一部分,但它因其强大的功能而被...
java魔法类:Unsafe应用
Pollexor 是 Thumbor 图片服务的 JAVA 客户端,兼容 Android 平台。... .toUrl()// Produces: /unsafe/200x100/filters:round_corner(10,255,255,255):watermark(/unsafe/200x100/example.c 标签:Pollexor
【开源项目-lucas-clemente-quic-go.zip】是一个基于Go语言实现的QUIC协议服务器端开源项目。QUIC(Quick UDP Internet Connections)是由Google设计并推广的一种低延迟、高性能的网络传输协议,旨在替代传统的TCP...
24. **/unsafe**:允许使用不安全的C#代码,如指针操作。 25. **/warn**:设置警告级别,控制编译时警告的显示。 26. **/warnaserror**:将警告提升为错误,使得编译器在遇到警告时停止编译。 27. **/win32icon**...
- `/unsafe-`: 不允许不安全代码。 **20. @<file>:** 读取命令行参数文件。 ``` csc @buildparams.txt ``` **21. /help:** 显示帮助信息。 ``` csc /help ``` **22. /nologo:** 禁用显示版权信息。 ``` csc /...
《深入解析Java sun.misc.Unsafe》 ...不过,了解`Unsafe`的工作原理对于提升对Java内存模型和并发编程的理解是非常有益的。在研究高性能、低延迟或特殊场景下的优化时,`Unsafe`可能会成为一种有效的解决方案。
Java 魔法类 Unsafe 详解 Java SPI 机制详解 Java 语法糖详解 集合 知识点/面试题总结 : Java 集合常见知识点&面试题总结(上) (必看 ) Java 集合常见知识点&面试题总结(下) (必看 ) Java 容器使用注意事项总结 ...
Java 魔法类 Unsafe 详解 Java SPI 机制详解 Java 语法糖详解 集合 知识点/面试题总结: Java 集合常见知识点&面试题总结(上) (必看 ) Java 集合常见知识点&面试题总结(下) (必看 ) Java 容器使用注意事项总结 源码...
Java序列化详解泛型&通配符详解Java 引用机制详解Java代理模式详解BigDecimal 详细解Java 魔法类 Unsafe 详细解Java SPI 机制详解Java语法糖详解集合知识点/面试题总结:Java集合常见知识点&面试题总结(上)(必看...
// 编译命令:csc /unsafe UnSafeSwap.cs using System; class Program { public static void Main() { int a = 2; int b = 9; Console.WriteLine("交换前:a = {0}, b = {1}", a, b); // 不安全语句 ...
虽然`monitorEnter`、`tryMonitorEnter`和`monitorExit`已不建议使用,但`compareAndSwapInt`等CAS方法是无锁编程的关键,广泛应用于`Atomic`系列类中,以提高并发性能。 六、挂起与恢复 `park`和`unpark`方法用于...
本文深入解析Java并发编程中的两个关键类:Atomic和Unsafe。这些类在提高Java并发操作的效率和安全性方面扮演着至关重要的角色。原子操作的核心:原子操作是不可分割的操作单元,确保数据的一致性和完整性。Java通过...
Java 魔法类 Unsafe 详解 Java SPI 机制详解 Java 语法糖详解 集合 知识点/面试题总结: Java 集合常见知识点&面试题总结(上) (必看 ) Java 集合常见知识点&面试题总结(下) (必看 ) Java 容器使用注意事项总结 源码...
该软件包了解unsafe标记,以允许使用不安全的语义: 解码为结构体时,您需要将字段名称读取为字符串,以便找到映射到其的结构体字段。 使用unsafe将绕过[]byte->string转换的分配和复制开销。 要使用它,必须在...
Java序列化详解泛型&通配符详解Java 引用机制详解Java代理模式详解BigDecimal 详细解Java 魔法类 Unsafe 详细解Java SPI 机制详解Java语法糖详解集合知识点/面试题总结:Java集合常见知识点&面试题总结(上)(必看...
实现Socket通信。 /// /// 网络通讯事件模型委托 /// </summary> public delegate void NetEvent(object sender, NetEventArgs e); /// /// 提供TCP连接服务的服务器类 /// /// 版本: 1.1 /// 替换版本:...
<name>hbase.unsafe.stream.capability.enforce</name> <value>false</value> </property> ``` 运行 HBase 1. 运行 ssh localhost 2. 运行 hadoop——start-dfs.sh 3. 运行 hbase——start-hbase.sh 4. 运行 ...
在Java并发编程中,理解和掌握并发锁的原理与实现至关重要,因为它们是解决多线程环境下的互斥和同步问题的关键。本文将基于JDK源码解析Java领域中的并发锁,探讨AQS基础同步器、LockSupport、Condition接口、Lock...
### Java synchronized 关键字原理与自定义锁实现详解 #### 一、Java synchronized 关键字原理 `synchronized` 是 Java 中的关键字之一,用于实现线程间的同步控制,确保共享资源的安全访问。它主要应用于以下两种...