- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java并发编程深入理解之Synchronized的使用及底层原理详解 上由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
多线程编程中,有可能会出现多个线程同时访问同一个共享、可变资源的情况,这个资源我们称之其为临界资源;这种资源可能是:对象、变量、文件等.
当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那就称这个对象是线程安全的,否则就是非线程安全的.
互斥同步(Mutual Exclusion & Synchronization)是一种最常见也是最主要的并发正确性保障手段。同步是指在多个线程并发访问共享数据时,保证共享数据在同一个时刻只被一条(或者是一些,当使用信号量的时候)线程使用。而互斥是实现同步的一种手段,临界区(Critical Section)、互斥量(Mutex)和信号量(Semaphore)都是常见的互斥实现方式.
在Java里面,最基本的互斥同步手段就是synchronized关键字,另外还有从JDK1.5开始引入了JUC里面的Lock接口,其中用的比较多的就是ReentrantLock,后面也会进行介绍.
synchronized是JVM内置的,是可重入的,其使用方法有三种:加在static修饰的静态方法上,加在普通方法上,同步代码块三种方式.
从上面可以看出synchronized锁的其实都是对象.
synchronized是基于JVM内置锁实现,通过内部对象Object Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器锁的实现依赖底层操作系统的Mutex lock(互斥锁)实现,它是一个重量级锁性能较低。当然,JVM内置锁在1.5之后版本做了重大的优化,如锁粗化(Lock Coarsening)、锁消除(Lock Elimination)、轻量级锁(Lightweight Locking)、偏向锁(Biased Locking)、适应性自旋(Adaptive Spinning)等技术来减少锁操作的开销,内置锁的并发性能已经基本与Lock持平.
注意:只有synchronized锁升级为重量级锁时才会用到Object Monitor(监视器锁).
synchronized关键字被编译成字节码后会被翻译成monitorenter 和monitorexit 两条指令分别在同步块逻辑代码的起始位置与结束位置.
1
2
3
4
5
6
7
8
|
public
class
TestSynchronized {
private
Object obj =
new
Object();
public
void
testLock() {
synchronized
(obj) {
System.out.println(
"获取了锁"
);
}
}
}
|
我们通过javap -c TestSynchronized.class将上面代码的class文件进行反汇编,可以看到如下所示:我们看到了monitorenter 和monitorexit 两条指令,但是monitorexit却出现了两次,原因如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public void testLock();
Code:
0
: aload_0
1
: getfield
#3 // Field obj:Ljava/lang/Object;
4
: dup
5
: astore_1
6
: monitorenter
7
: getstatic
#4 // Field java/lang/System.out:Ljava/io/PrintStream;
10
: ldc
#5 // String 鑾峰彇浜嗛攣
12
: invokevirtual
#6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
15
: aload_1
16
: monitorexit
17
: goto
25
20
: astore_2
21
: aload_1
22
: monitorexit
23
: aload_2
24
: athrow
25
:
return
Exception table:
from
to target
type
7
17
20
any
20
23
20
any
|
上面提到了,只有synchronized锁升级为重量级锁时才会用到Object Monitor(监视器锁)。我们看一下Object Monitor的实现机制是什么?查看OpenJDK源码可以看到Object Monitor由C++语言实现,打开JDK源码目录 “jdk\hotspot\src\share\vm\runtime“可以看到objectMonitor.hpp,这个就是监视器锁的实现,截取一段代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
ObjectMonitor() {
_header
=
NULL;
/
/
对象头
_count
=
0
;
/
/
记录加锁次数,锁重入时用到
_waiters
=
0
,
/
/
当前有多少处于wait状态的thread
_recursions
=
0
;
/
/
记录锁的重入次数
_object
=
NULL;
_owner
=
0
;
/
/
指向持有ObjectMonitor对象的线程
_WaitSet
=
NULL;
/
/
处于wait状态的线程,会被加入到_WaitSet
_WaitSetLock
=
0
;
_Responsible
=
NULL ;
_succ
=
NULL ;
_cxq
=
NULL ;
FreeNext
=
NULL ;
_EntryList
=
NULL ;
/
/
处于等待加锁block状态的线程,会被加入到该列表
_SpinFreq
=
0
;
_SpinClock
=
0
;
OwnerIsThread
=
0
;
_previous_owner_tid
=
0
;
}
|
其中几个比较重要的字段:
ObjectMonitor的加锁解锁过程如下图所示,ObjectMonitor中有两个队列,_WaitSet 和 _EntryList,用来保存ObjectWaiter对象列表(每个等待锁的线程都会被封装成ObjectWaiter对象);整个monitor运行的机制过程如下:
下节将会介绍一下synchronized的锁优化和锁升级过程 。
到此这篇关于Java并发编程深入理解之Synchronized的使用及底层原理详解 上的文章就介绍到这了,更多相关Java 并发编程 Synchronized内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/u012988901/article/details/112006772 。
最后此篇关于Java并发编程深入理解之Synchronized的使用及底层原理详解 上的文章就讲到这里了,如果你想了解更多关于Java并发编程深入理解之Synchronized的使用及底层原理详解 上的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试在多线程环境中实现某种累积逻辑;我想知道没有 lock 和 synchronized 关键字是否有更好/更快的方法来做到这一点?以下是我当前的代码: public class Concurr
我需要帮助构建一个实现信号量的监视器,简单的 C 示例就可以。 这是为了证明可以在任何可以使用信号量的地方使用监视器。 最佳答案 如果您说允许使用互斥锁/condvars,请检查: #include
我已经构建了一些返回部分产品目录的 ajax,并且我正在尝试将 xml 输出到文档中,到目前为止,这是我所拥有的: $("#catalog").append("Item NamePriceDe
很抱歉,如果我的问题之前已经被问过,或者它太明显了,但我真的需要澄清这一点。感谢您的帮助。 在多用户界面中,如果来自不同用户的相同事务同时到达服务器,会发生什么? 我有下一张表: create tab
这可能是一个愚蠢的问题,但是这个程序的输出(它的方式)可以为零吗? public class Test2{ int a = 0; AtomicInteger b = new Atomi
假设我本地主机上的一个网站处理每个请求大约需要 3 秒。这很好,正如预期的那样(因为它在幕后进行了一些奇特的网络)。 但是,如果我在选项卡(在 firefox 中)中打开相同的 url,然后同时重新加
我对 MongoDB 的读锁定有点困惑。单个集合可以支持多少个并发读取操作? 最佳答案 如 tk 给出的链接中所写:http://www.mongodb.org/pages/viewpage.acti
如果有四个并发的 CUDA 应用程序在一个 GPU 中竞争资源会发生什么这样他们就可以将工作卸载到图形卡上了? Cuda Programming Guide 3.1 提到那里 某些方法是异步的: 内核
👊上次的百度面试遇到了关于spark的并发数的问题,今天我们就来将这些问题都一并解决一下,图画的的有点丑,还行大家见谅,百度实习的问题我放在了下面的链接👇: 链接: 2022百度大数据开发工程师实
我对 Groovy 线程有疑问。 我的任务是以某种方式翻译给定目录中的每个文件 并将生成的输出放在其他目录中的文件中。 我编写了以下代码,该代码有效: static def translateDir(
Java中的同步和锁定有什么区别? 最佳答案 synchronized是语言关键字;锁是对象。 当一个方法或代码块被标记为同步时,您是说该方法或代码块必须先获得某个锁对象(可以在同步的语法中指定)才能
我需要创建一个能够同时处理来自客户端的多个请求的并发 RPC 服务器。 使用 rpcgen linux编译器(基于sun RPC),不支持-A为并发服务器创建 stub 的选项。 (-A 选项在 so
System.out.println("Enter the number of what you would like to do"); System.out.println("1 = Manuall
我正在将我的应用程序移植到 iOS 8.0 并注意到 UIAlertView 已被弃用。 所以我改变了使用 UIAlertController 的方法。这在大多数情况下都有效。 除了,当我的应用程序打
我正在逐行同时读取两个文本文件。 我特别想做的是当lineCount在每个线程上都是相同的我想看看扫描仪当前正在读取的字符串。 我环顾四周寻找可以实现的某些模式,例如 Compare and Swap
我正在阅读 Java Concurrency in Practice .在章节中断政策部分 取消和关闭 它提到 A task should not assume anything about the
我正在尝试学习线程,互斥等的基础知识。遵循here的文档和示例。在下面的代码中,我得到预期的输出。问题: 想确认我是否有任何陷阱?我们如何改善下面的代码? 我的线程在哪一行尝试获取互斥锁或正在等待互斥
并发是指两个任务在不同的线程上并行运行。但是,异步方法并行运行,但在同一个线程上。这是如何实现的?另外,并行性怎么样? 这三个概念有什么区别? 最佳答案 并发和并行实际上与您正确推测的原理相同,两者都
以此ConcurrentDouble类定义为例: public class ConcurrentDouble { public double num = 0; public void subt
在得知并发确实增加了许多人的吞吐量后,我一直计划在项目中使用并发。现在我在多线程或并发方面还没有做太多工作,因此决定在实际项目中使用它之前学习并进行简单的概念验证。 以下是我尝试过的两个示例: 1.
我是一名优秀的程序员,十分优秀!