Java synchronize!不全面?这篇文章就够了!

Synchronize 是什么

synchronized,中文意思为同步,用于多线程资源共享与维护的最常用手段。它通过线程互斥的手段,保存证了资源的原子性。


使用如下:

<code>

synchronized

(

o

) { } /<code>

实现的原理

本文要讲的主要是1.6以后的版本,1.6版本针对synchronize做了使用优化,根据使用的情使用不同的锁。

包括:

偏向锁
1:当线程取得锁时, warkword偏向锁位标记为1,并记录使用该对象的线程指针。
2:当线程尝试向 偏向锁对象 取锁时, 锁将升级为轻量级锁。

轻量级锁
1.当线程拿不到锁对象时,线程不会释放,而是继续while循环空转,直到获取到锁为止。
2.轻量级锁的Markword会记录lock Record的指针,lock Record会记录对象自旋的次数,当它达到一定自旋次数之后,jvm会将它升级为重量级锁。

<code>优点:
无需从用户态转向内核态,在锁竞争比较低的情况,线程只需消化几个时钟周期就能获得锁,所以性能很快。
缺点:
线程自旋是需要消耗cpu性能的,在锁竞争激烈的情况,空转的线程数量和自旋的次数会变高,此时会白白浪费cpu时钟周期。/<code>

重量级锁
jvm对重量级锁的实现,是需要依赖操作系统底层的,操作系统底层维护了一个锁的队列,当jvm所有重量级锁的申请,都需要在这个锁队列里面进行排队,线程需要从用户态转向内核态,排队过程线程被挂起,无需消耗cpu时钟频率,直到轮到这个线程获取锁时,系统才会唤醒该争用的线程。

<code>优点:
不消耗cpu,特别时对于大量锁的争用时。
缺点:
等待锁的时间长。/<code>

synchronize 锁升级过程

如下图所示:

  1. 初始化,无锁。
  2. 有且只有一线程取得锁时,为偏向锁。
  3. 对象已被锁,并有其它线程尝试取锁时,锁升级为轻量级锁。
  4. 锁状态为轻量级锁,并有更多(达到临界值时)的线程尝试去取锁,轻量级锁将升级为重量级锁。
Java synchronize!不全面?这篇文章就够了!

锁升级过程

线程获取锁过程

如下图所示:

  1. 对象无锁时。直接取得锁
  2. 有锁并且是轻量级锁,线程自旋取得锁。
  3. 有锁并且是重量级锁,线程阻塞,等待锁释放再取得锁。
  4. 取得锁后,用完释放。
Java synchronize!不全面?这篇文章就够了!

线程获取锁过程

锁状态与markword

对象锁的状态是存在markword记录的,如下图所示:

无锁时,锁标志为01,另外存储了其它各种信息(包括偏向锁状态,分代年龄,hashcode)。

偏向锁时,锁标志为01,另外存储了取得锁的线程。

轻量锁时,锁标志为00,存储了线程栈Lock Record的指针。

重量级锁时,锁标志为10,存储了,重量级锁的指针。

Java synchronize!不全面?这篇文章就够了!

锁状态与markword

实例

下面将通过一个实例,结合markword一步一步地演示synchronize 锁的升级过程。

测试过程
  1. 引入JOL打印出对象的结构(关键是markword)。
  2. 模拟无锁,单线程锁,2个线程,100个级线。
  3. 输出对应的markword。

pom.xml 配置

<code> 

<

project

xmlns

=

"http://maven.apache.org/POM/4.0.0"

xmlns:xsi

=

"http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation

=

"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"

>

<

modelVersion

>

4.0.0

modelVersion

>

<

groupId

>

SynchronizeTest

groupId

>

<

artifactId

>

SynchronizeTest

artifactId

>

<

version

>

1.0-SNAPSHOT

version

>

<

dependencies

>

<

dependency

>

<

groupId

>

org.openjdk.jol

groupId

>

<

artifactId

>

jol-core

artifactId

>

<

version

>

0.9

version

>

dependency

>

dependencies

>

project

>

/<code>

代码

<code>

import

org.openjdk.jol.info.ClassLayout;

public

class

ApplicationTest

{

static

volatile

String strMsg =

""

;

static

volatile

String str2Msg =

""

;

public

static

void

main

(String[] args)

throws

InterruptedException

{ Thread.sleep(

5000

); Object o =

new

Object();

new

Thread() {

public

void

run

()

{

while

(

true

) {

if

(str2Msg.equals(strMsg) ==

false

) { str2Msg = strMsg; System.out.print(str2Msg); } } } }.start(); strMsg = ClassLayout.parseInstance(o).toPrintable(); }

public

static

void

SynsTest

(

int

num,

final

Object o)

throws

InterruptedException

{

for

(

int

i =

0

; i < num; i++) { System.out.println(

"启开第"

+ (i +

1

) +

"线程"

);

new

Thread() {

public

void

run

()

{

synchronized

(o) {

for

(; ; ) { strMsg = ClassLayout.parseInstance(o).toPrintable();

try

{ Thread.sleep(

100

); } }

catch

(InterruptedException e) { e.printStackTrace(); } } } }.start(); } } }/<code>
测试步骤:

第一步:
1、o对象初始化后,直接打印出o对象。解注以下代码:

<code>  		 
         strMsg = ClassLayout.parseInstance(o).toPrintable();
         
         
         
         
         
         
/<code>

2、运行结果如下图所示: 状态位为01,断定为无锁


Java synchronize!不全面?这篇文章就够了!

无锁

第二步:


1、开启1个线程取锁。解注以下代码:

<code> 		 
         
         
        

SynsTest

(

1

, o); /<code>

2、结果如下图所示:状态位为01,后面还记录着 对应的线程指针,断定为 偏向锁


Java synchronize!不全面?这篇文章就够了!

偏向锁

第三步:


1、开启2个线程最锁。解注以下代码:

<code>  		 
         
         
         
         
         

SynsTest

(

2

,o); /<code>

2、如下图所示:状态位为00,断定为轻量级锁


Java synchronize!不全面?这篇文章就够了!

轻量级锁

第四步:
1、开始100个线程取锁。解注以下代码:

<code> 
         
         
         
         
         
         
         

SynsTest

(

100

,o);/<code>

2、结果如下图所示:状态位为10,断定为重量级锁


Java synchronize!不全面?这篇文章就够了!

重量级锁

PS
因为偏向锁默认在jvm启动4秒后才启动。所以在这里设置等待5秒。具体的结果与配置有关。本机测试用的环境如下,所有配置都是默认的。

Java synchronize!不全面?这篇文章就够了!

可以通过以下命令打印出配置的参数:


Java synchronize!不全面?这篇文章就够了!

小编整理来自:https://blog.csdn.net/richyliu44/article/details/105327885,CSDN博主「Richy Liu」

今天小编整理的这篇干货您觉得怎么样呢?是否对自己有一定的提升呢,如果您觉得还可以的话,不妨点个关注收藏转发一下呐!与小编一起进步!您的支持就是小编最大的动力!谢谢啦!关注我!每天更新哦!绝对技术干货!


分享到:


相關文章: