Android 线程安全(二) synchronized

synchronized 关键字

一、使用方式

1、修饰普通方法,锁对象为类实例
2、修饰静态方法,锁对象为类class实例
3、修饰代码块,锁对象为括号里的对象

    private synchronized void fun(){//  普通方法互斥

    }

    public synchronized static void funStatic(){//  静态方法互斥

    }

        synchronized (object){
			//代码块互斥
        }

这样使用后各线程都是互斥的,保证了线程安全。

二、锁优化

参考自《深入理解java虚拟机》java 1.6 以后 jvm 优化了 synchronized。一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。

优化
1、锁粗化(Lock Coarsening):也就是减少不必要的紧连在一起的unlock,lock操作,将多个连续的锁扩展成一个范围更大的锁,减少了锁获取释放的次数。

private void fun1(){
        synchronized (object){
            //do somethings 1
        }
        synchronized (object){
            //do somethings 2
        }
        synchronized (object){
            //do somethings 3
        }
    }
    //粗化合到一起
    private void fun2(){
        synchronized (object){
            //do somethings 1
            //do somethings 2
            //do somethings 3
        }
    }

2、锁消除(Lock Elimination):锁削除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。
3、适应性自旋(Adaptive Spinning):自旋是指获取锁时,先不挂起线程,而是while循环使用CAS的方式获取,这样效率更高。适应性自旋则会根据之前当前线程获取锁的结果,来动态调整while循环的次数, 优化了效率,更“智能”。

java中每个对象都可以作为锁对象,因为每个对象都拥有一个对象头,记录对象hashCode、GC分代、偏向锁编程ID,锁状态等。
正如图展示的这部分内存,不是固定的,在不通的锁状态有不通的指向。

对象头
1、无锁状态,如果jvm检测到不可能有多线程执行此方法,则是无锁状态,内存就是表格第一行描述的那样。表格中第1行。
2、加入一个线程调用了方法或者代码块,锁对象的线程ID使用CAS标记当前线程,在没有其他线程调用的情况下,不会再CAS,直接就调用了。表格中第5行。
3、如果在偏向锁的状态下,有其他线程调用,线程ID与当前调用线程不一致,则 膨胀为轻量级锁。膨胀过程为:使用CAS在当前线程栈帧复制此对象头信息保存在Lock Recorder空间,并将锁对象头指向此栈帧中的内存。就是说当前线程获取了此轻量级锁。表格中第2行。
如果一个线程调用方法,使用CAS复制失败,发现markwork指向当前栈帧内存,就直接调用了。

4、如果一个线程调用方法,使用CAS复制失败,而且markword不指向当前栈帧,则膨胀为重量级锁,将markwork指向锁对象。本线程挂起,并等待持有锁释放。表格第三行。

三、重量级锁

重量级锁会将线程挂起,等待执行。

重量级锁

上图简单描述多线程获取锁的过程,当多个线程同时访问一段同步代码时,首先会进入 Entry Set当线程获取到对象的monitor 后进入 The Owner 区域并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count加1,若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 WaitSet集合中等待被唤醒。若当前线程执行完毕也将释放monitor(锁)并复位变量的值,以便其他线程进入获取monitor(锁)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值