东莞市盛裕绒艺玩具有限公司

东莞市盛裕绒艺玩具有限公司

esball世博客户端

13927392878
联系方式
全国服务热线: 13927392878

咨询热线:13962196778
联系人:刘源德
地址:四川省绵阳市.涪城区红星街62号

Java并发编程原理与实战九:synchronized的原理与使用

来源:esball世博客户端   发布时间:2019-06-26   点击量:266

一、理论层面

内置锁与互斥锁

修饰普通方法、修饰静态方法、修饰代码块

package com.roocon.thread.t3;public class Sequence { private static int value; // synchronized放在普通方法上,内置锁就是当前方法的实例 public synchronized int getNext(){ return value++; } // synchronized修饰静态方法,内置锁就是当前的Class字节码对象Sequence.class public static synchronized int getPrevious(){ return value--; } public int xx(){ // synchronized修饰静态代码块,则锁的是任意一个对象 /* synchronized (this){ } synchronized (Integer.valueOf(value)) { } synchronized (Sequence.class) { } */ synchronized (Sequence.class) { if (value > 0) { return value; }else { return -1; } } } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getName()+" "+sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }}

 

二、JVM层面

查看xx方法同步代码块字节码:

查看同步方法字节码:

任何对象都可以作为锁,那么锁信息又存在对象的什么地方呢?

存在对象头中。

 

对象头中的信息:

  Mark Word

  Class Metadata Address 类的类型地址

  Array Length

 

1.偏向锁:

每次获得锁和释放锁会浪费资源(消耗时间),很多情况下,竞争锁不是由多个线程,而是由一个线程在使用。线程在获取锁时,会依据对象头Mark word信息进行判断执行。

对象头Mark word中会保存如下信息:

  线程id

  Epoch

  对象的分代年龄信息

  是否是偏向锁

  锁标志位

偏向锁在获取锁之后,如果没有竞争,也就是一直是这个线程在获取锁,那么当这个线程第二次再来进入该方法时,不需要再去获取锁了,也不需要释放锁,这样,就节省了大量的获取锁释放锁的资源。那么,什么时候会释放锁呢?只有当存在竞争时,才会去释放锁。

偏向锁适用于什么场景?

只有一个线程在访问同步代码块的场景。

 

2.轻量级锁:可以同时让多个线程进入同步代码块。自旋锁就是轻量级锁。

轻量级锁是如何加锁的?

在线程执行同步代码块之前,jvm会先在当前线程的栈帧中创建用于存储锁记录的存储空间。

(栈帧是什么?虚拟机栈中存储的是一个一个的栈帧,栈帧中存储了方法的执行信息,每个方法都会伴随着栈帧的进栈和出栈)

然后呢,并将对象头中的mark word复制到锁记录中。然后呢,开始竞争锁就可以了。竞争成功之后,markword就改变了,会将锁标志位改成轻量级锁。接着,开始执行同步体。

另外一个线程也想获得该锁。同样,它也将对象头中的mark word复制到锁记录中,它发现已经被其他线程获得了锁,所以它修改不成功。于是,它就不停的去修改,不停的失败,直到第一个线程把这个锁释放了,它就可以修改成功了。刚才这一个过程,就是所谓的自旋锁。

 

3.重量级锁

什么是重量级锁?就是,这个线程获得锁进入之后,其他线程必须在外面等待。synchronized就是重量级锁。

 

三、总结

上面只是对synchronized 如何实现同步功能的一个视频学习总结,更加细节的深入原理可以参考下面两篇文章:

synchronized的实现原理    

深入理解Java并发之synchronized实现原理

 

参考资料:

《java并发编程与实战》龙果学院

, 1, 0, 9);

相关产品

COPYRIGHTS©2017 esball世博客户端 ALL RIGHTS RESERVED 备案号:266