美文网首页
Android:锁总结

Android:锁总结

作者: 我在等你回复可你没回 | 来源:发表于2018-07-30 17:58 被阅读156次

java 锁,分为偏向锁,轻量级锁,重量级锁。

问题一:这么多种锁,是否有例子呢?
没有,这些都是jvm的配置,都是对语法synchronize的优化。
例如jvm禁用偏向锁,就要配置
-XX:-UseBiasedLocking

问题二:这三种锁有什么区别,适用于什么场景
这三种锁效率从高到低:偏向锁,轻量级锁,重量级锁
重量级锁:使用的是linux的互斥量mutex实现。非常耗资源
轻量级锁(自旋锁):使用cas来实现锁。使用与线程交替访问资源的情况,可以减少mutex的使用。加锁和解锁都是使用一次cas操作。
cas常见一个Unsafe的类来实现。
例如自增的话,需要获取当前值,然后+1。但是获取当前值后的1ms,可能只就被别的线程改了。
所以,再加1之前,【先跟内存判断一下,判断完在内存直接+1】。内存判断跟+1这个在cpu控制了,是一步的。不会说判断了之后,会不会有被改了的问题!!!!

import sun.misc.Unsafe;  
  
public class AtomicInteger extends Number implements java.io.Serializable {  
    private static final long serialVersionUID = 6214790243416807050L;  
  
    // setup to use Unsafe.compareAndSwapInt for updates  
    private static final Unsafe unsafe = Unsafe.getUnsafe(); </span> 
    private static final long valueOffset;  
  
    static {  
      try {  
        valueOffset = unsafe.objectFieldOffset  
            (AtomicInteger.class.getDeclaredField("value"));  
      } catch (Exception ex) { throw new Error(ex); }  
    }  
  
    private volatile int value;  
 
   //如果当前值 ==预期值,则以原子方式将该值设置为给定的更新值。如果成功就返回,否则返回,并且不修改原值。  
public final boolean compareAndSet(int expect, int update) {  
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  </span>
    }  
 
    //以原子方式将当前值加1。相当于线程安全版本的i++操作。  
    public final int getAndIncrement() {  
        for (;;) {  
            int current = get();  
            int next = current + 1;  
            if (compareAndSet(current, next))  
                return current;  
        }  
    }  
  
 
}  

偏向锁:只有一次cas操作,就是更新object mark work的Thread ID。不需要拷贝mark work到线程栈中。


image.png
image.png

问题三:mark work是什么?


image.png

在锁对象头中,用于记录锁状态滴。下图是不同锁的mark work状态

问题四:偏向锁只能有一个线程A吗?
不是滴,同一时刻只有一个线程访问锁对象即可,加入A线程访问完了,B线程再访问,仍然是偏向锁。

问题五:如何判断线程CAS获取轻量级锁成功呢?
就是线程去CAS改变锁对象的Mark work的值,能改成功,就说明获取到锁了。那就mark work改成什么值呢?
答案是将mark work当成一个指针,指向线程A,如何指向线程A,直线线程A的栈的某个地址,这个地址叫做lock record,
lock record中owner记录着这个这个线程持有了哪个对象的锁。

问题六:偏向锁如何升级为轻量级锁
某一个线程发现锁状态出于偏向锁状态,但是Thread ID又不是自己,然后然后查看Thread ID是不是在跑,在跑的话,就暂停它,更新mark work为指针指向Thraed ID线程,并把mark word的锁标志写成00偏向锁,

问题七:轻量级锁如何解锁
解锁时,判断一下markwork有没有变,有变就升级成重量级锁,没有变的话,就将原来的mark work拷贝回去。这是等待的线程就CAS成功啦!!
知乎神图如下:
https://www.zhihu.com/question/53826114/answer/236363126

image.png

问题三:类锁与对象锁

链接:
https://blog.csdn.net/hsuxu/article/details/9472381
https://blog.csdn.net/truong/article/details/74942155
https://blog.csdn.net/wolegequdidiao/article/details/45116141
https://blog.csdn.net/zqz_zqz/article/details/70233767

相关文章

网友评论

      本文标题:Android:锁总结

      本文链接:https://www.haomeiwen.com/subject/cfpfvftx.html