Java多线程 - synchronized的使用和原理

简介:

synchronized是一种独占式的重量级锁,在运行到同步方法或者同步代码块的时候,让程序的运行级别由用户态切换到内核态,把所有的线程挂起,通过操作系统的指令,去调度线程。

1. synchronized的使用

       1、某个对象实例内

此作用域内的synchronized锁 ,可以防止多个线程同时访问这个对象的synchronized方法

一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法。

不同对象实例的synchronized方法是不相干预的。也就是说,其它线程可以同时访问此类下的另一个对象实例中的synchronized方法

class SynchronizedDemo {

    public synchronized void m() {
        System.out.printf("WUST");
    }

    public void m2() {
        synchronized(this) {
            System.out.printf("WUST");
        }
    }
}

        2、某个类

          此作用域下,可以防止多个线程同时访问这个类中的synchronized方法。也就是说此种修饰,可以对此类的所有对象实例起作用。

          注意一点,synchronized关键字是不能继承的,也就是说,基类的方法synchronized fun(){} 在继承类中并不自动是synchronized fun(){},而是变成了fun(){}。继承时,需要显式的指定它的某个方法为synchronized方法。

class SynchronizedDemo {

    public static synchronized void m() {
        System.out.printf("WUST");
    }

    public void m2() {
        synchronized(ClassName.class) {
            System.out.printf("WUST");
        }
    }
}

2. 字节码分析

对象被创建在堆中。并且对象在内存中的存储布局方式可以分为3块区域:对象头、实例数据、对齐填充。

对象头来说,主要是包括俩部分信息:

自身运行时的数据,比如:锁状态标志、线程持有的锁…等等。(此部分内容被称之为Mark Word)

另一部分是类型指针:JVM通过这个指针来确定这个对象是哪个类的实例。

1、synchronized代码块的底层实现

javap 之后:

根据虚拟机规范要求,在执行monitorenter指令时,首先要尝试获取对象锁,也就是上文我们提到了monitor对象。如果这个对象没有被锁定,或者当前线程已经拥有了这个对象的锁,那么就把锁的计数器(_count)加1。当然与之对应执行monitorexit指令时,锁的计数器(_count)也会减1。

2、方法上

字节码中并没有monitorenter指令和monitorexit指令,取得代之的是ACC_SYNCHRONIZED标识,JVM通过ACC_SYNCHRONIZED标识,就可以知道这是一个需要同步的方法,进而执行上述同步的过程,也就是_count加1,这些过程。

3. synchronized 作用

1、确保线程互斥的访问同步代码

2、保证共享变量的修改能够及时可见

3、有效解决重排序问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值