Juc06_Lock8锁问题、字节码层面看Synchronized、反编译synchronized锁

简介: ①. Lock8 8锁问题②. 从字节码角度分析synchronized实现③. 反编译synchronized锁的是什么

①. Lock8 8锁问题


  • ①. Lock8锁问题


  1. 标准访问有ab两个线程,请问先打印邮件还是短信


  1. sendEmail方法暂停3秒钟,请问先打印邮件还是短信


  1. 新增一个普通的hello方法,请问先打印邮件还是hello


  1. 有两部手机,请问先打印邮件还是短信


  1. 两个静态同步方法,同1部手机,请问先打印邮件还是短信


  1. 两个静态同步方法, 2部手机,请问先打印邮件还是短信


  1. 1个静态同步方法,1个普通同步方法,同1部手机,请问先打印邮件还是短信


  1. 1个静态同步方法,1个普通同步方法,2部手机,请问先打印邮件还是短信


②. 代码展示


class Phone{ //资源类
    public static synchronized void sendEmail() {
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("-------sendEmail");
    }
    public synchronized void sendSMS()
    {
        System.out.println("-------sendSMS");
    }
    public void hello()
    {
        System.out.println("-------hello");
    }
}
public class Lock8Demo{
    public static void main(String[] args){//一切程序的入口,主线程
        Phone phone = new Phone();//资源类1
        Phone phone2 = new Phone();//资源类2
        new Thread(() -> {
            phone.sendEmail();
        },"a").start();
        //暂停毫秒
        try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }
        new Thread(() -> {
            //phone.sendSMS();
            //phone.hello();
            phone2.sendSMS();
        },"b").start();
    }
}
/**
 *
 * ============================================
 *  1-2
 *  *  一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,
 *  *  其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一的一个线程去访问这些synchronized方法
 *  *  锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
 *
 *  3-4
 *  *  加个普通方法后发现和同步锁无关
 *  *  换成两个对象后,不是同一把锁了,情况立刻变化。
 *
 *  5-6 都换成静态同步方法后,情况又变化
 *  三种 synchronized 锁的内容有一些差别:
 * 对于普通同步方法,锁的是当前实例对象,通常指this,具体的一部部手机,所有的普通同步方法用的都是同一把锁——实例对象本身,
 * 对于静态同步方法,锁的是当前类的Class对象,如Phone.class唯一的一个模板
 * 对于同步方法块,锁的是 synchronized 括号内的对象
 *
 *  7-8
 *    当一个线程试图访问同步代码时它首先必须得到锁,退出或抛出异常时必须释放锁。
 *  *
 *  *  所有的普通同步方法用的都是同一把锁——实例对象本身,就是new出来的具体实例对象本身,本类this
 *  *  也就是说如果一个实例对象的普通同步方法获取锁后,该实例对象的其他普通同步方法必须等待获取锁的方法释放锁后才能获取锁。
 *  *
 *  *  所有的静态同步方法用的也是同一把锁——类对象本身,就是我们说过的唯一模板Class
 *  *  具体实例对象this和唯一模板Class,这两把锁是两个不同的对象,所以静态同步方法与普通同步方法之间是不会有竞态条件的
 *  *  但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁。
 **/


②. 从字节码角度分析synchronized实现


  • ①. 反编译:javap -v -p *.class > 类.txt 将进行输出到txt中


  • ②. synchronized有三种应用方式


  1. 作用于实例方法,当前实例加锁,进入同步代码前要获得当前实例的锁


  1. 作用于代码块,对括号里配置的对象加锁


  1. 作用于静态方法,当前类加锁,进去同步代码前要获得当前类对象的锁


  • ③. synchronized同步代码块


  1. 实现使用的是monitorenter和monitorexit指令


微信图片_20220106184706.png


一定是一个enter和两个exit吗?


(不一定,如果方法中直接抛出了异常处理,那么就是一个monitorenter和一个monitorexit)



微信图片_20220106184727.png


④. synchronized普通同步方法


(调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程会将先持有monitor然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放minotor)


微信图片_20220106184745.png


⑤. synchronized静态同步方法


(ACC_STATIC、ACC_SYNCHRONIZED访问标志区分该方法是否静态同步方法)


微信图片_20220106184809.png


③. 反编译synchronized锁的是什么


①. 任何一个对象都可以成为一个锁,在HotSpot虚拟机中,monitor采用ObjectMonitor实现


②. 上述C++源码解读


ObjectMonitor.java — ObjectMonitor.cpp — ObjectMonitor.hpp


ObjectMonitor.hpp(底层源码解析)


微信图片_20220106184841.png


③. 阿里开发手册说明


高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁


相关文章
|
2月前
|
安全 算法 Java
Java多线程基础-15:Java 中 synchronized 的优化操作 -- 锁升级、锁消除、锁粗化
`synchronized`在Java并发编程中具有以下特性:开始时是乐观锁,竞争激烈时转为悲观锁;从轻量级锁升级至重量级锁;常使用自旋锁策略;是不公平且可重入的;不支持读写锁。
28 0
|
2月前
|
Java
浅谈Java的synchronized 锁以及synchronized 的锁升级
浅谈Java的synchronized 锁以及synchronized 的锁升级
12 0
|
2月前
|
存储 算法 Java
JUC并发编程之Synchronized锁优化
HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
|
2月前
|
Java
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
|
安全 Java
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁的简单示例
92 1
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁
|
安全 Java 对象存储
浅谈synchronized锁原理
保证线程安全的一个重要手段就是通过加锁的形式实现,今天盘点一下Java中锁的八股文
136 0
线程同步的方法:Synchronized、Lock、ReentrantLock分析
线程同步的方法:Synchronized、Lock、ReentrantLock分析
|
安全 Java 编译器
多线程安全问题原理和解决办法Synchronized和ReentrantLock使用与区别
多线程安全问题原理和解决办法Synchronized和ReentrantLock使用与区别
|
Java 编译器 API
Java并发编程 - Synchronized & ReentrantLock 区别
Java并发编程 - Synchronized & ReentrantLock 区别
87 0
Java并发编程 - Synchronized & ReentrantLock 区别
|
存储 算法 Java
JVM Synchronized 锁实现
本文着重介绍 JVM 中 synchronized 锁相关的内容