2019-02-27 Sync关键字实现原理

2.线程安全关键字syncnized的实现原理?

  1. 悲观锁和乐观锁
    1. 悲观锁:总是假设最坏的情况,每次去拿数据时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会被阻塞知道它拿到锁,如synchronized和ReentrantLock
    2. 乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是再更伤心的时候会判断下再次期间别人有没有更新这个数据。
    3. 乐观锁一般使用版本号机制或者CAS算法实现
    4. ABA问题是乐观锁的一个常见问题:如果一个变量V初次读取时候是A值,并且在准备赋值的时候检查到它仍是A值,那么我们就能说明他的值没有被其他线程修改过吗?A-B-A,JDK1.5之后提供了AtomicStampedReference
    5. 循环时间长开销大:自旋CAS长时间不成功,会给CPU带来非常大的执行开销
    6. 只能保证一个共享变量原子操作
  2. CAS(Compare And Set或 Compare And Swap)解决多线程并行情况下使用锁造成性能损耗的一种机制
    1. 包含三个操作数:内存位置(V),预期原值(A),新值(B)。如果内存位置的值与预期值匹配,那么处理器会自动将该位置的值更新为新值;否则,处理器不做任何操作。
  3. Happens-before原则定义
    1. 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个之前
    2. 两个操作之间存在happens-bofore关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序合法。
  4. Happens-before原则规则
    1. 程序次序原则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
    2. 锁定原则:一个unLock操作先行发生于后面对同一个锁的lock操作
    3. volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
    4. 传递规则:A>B且B>C,那么A>C
    5. 线程启动规则:Thread对象的start()方法先行发生于此线程的每个动作
    6. 线程终端规则:对线程的interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
    7. 线程终结规则:线程中所有的操作都先行发生于线程的终止检测
    8. 对象终结规则:一个对象的舒适化完成先行发生他的finalize()方法的开始
  5. Java对象头
    1. 偏向锁:大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。
    2. 轻量级锁:线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的Mark Word赋值到锁记录中,然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。
  6. synchronized原理分析
    1. 代码块同步时,使用monitorenter和monitorexit指令实现,方法同步则是依赖方法修饰符ACC_SYNCHRONIZED来完成
    2. monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束和异常处

你可能感兴趣的:(2019-02-27 Sync关键字实现原理)