Loading

进程内并发(synchronized,volatile,cas)

线程周期

synchronized锁可重用

synchronized底层实现,早期JDK,重量级os实现

synchronized(Object)

这个Object不能用String常量、Integer、Long

  • markword记录线程ID(偏向锁
  • 如果线程争用,升级为 自旋锁 (while反复判断能否进入临界区)
  • 10次以后,升级为重量级锁(进入等待队列

自旋锁占用CPU,但不访问OS,在用户态,不在内核态

执行时间短,线程数少,自旋锁

执行时间长,线程多,系统锁

Volatile

保证线程可见性(无法保证原子性即无法替代synchronized关键字)

缓存一致性协议额

MESI

禁止指令重排cpu

  • DCL单例
  • Double Check Lock
  • loadfence原语指令
  • storefence原语指令

CAS(无锁优化 自旋,原语级别)

Compare And Swap

使用AtomicInteger实现锁(无锁/乐观锁)

public class _AtomicInteger{
  AtomicInteger count = new AtomicInteger(0);
  void m(){
    for(int i = 0; i < 10000; i++){
      count.incrementAndGet();// count++
    }
  }
}

伪代码

cas(V, Expected, New Value){
  if(V == E){
    V = New
    // try ag or fil
  }
}

ABA问题

某个线程执行过程中,先修改integer的值,然后执行具体方法,然后又把integer的值改回来

  • 解决方法:加版本号
  • A:1 B:2 A:3
  • cas(version)

版本号可以通过API AtomicStampedReference 实现

如果是基础类型,没有影响,如果是引用类型,可能线程对有间接寻址的对象做出改变,会导致无法判断

Unsafe(可以和C++一样直接操作内存)

内存管理

包括分配内存、释放内存等

利用copyMemory方法,我们可以实现一个通用的对象拷贝方法,无需再对每一个对象都实现clone方法,当然这通用的方法只能做到对象浅拷贝

非常规的对象实例化

allocateInstance()方法提供了另一种创建实例的途径

通常我们可以用new或者反射来实例化对象,使用allocateInstance()方法可以直接生成对象实例,且无需调用构造方法和其它初始化方法

这在对象反序列化的时候会很有用,能够重建和设置final字段,而不需要调用构造方法

操作类、对象、变量。

这部分包括了staticFieldOffset(静态域偏移)、defineClass(定义类)、defineAnonymousClass(定义匿名类)、ensureClassInitialized(确保类初始化)、objectFieldOffset(对象域偏移)等方法

数组操作

这部分包括了arrayBaseOffset(获取数组第一个元素的偏移地址)、arrayIndexScale(获取数组中元素的增量地址)等方法

arrayBaseOffset与arrayIndexScale配合起来使用,就可以定位数组中每个元素在内存中的位置

多线程同步

包括锁机制、CAS操作等

挂起与恢复

这部分包括了park、unpark等方法

内存屏障

这部分包括了loadFence、storeFence、fullFence等方法。这是在Java 8新引入的,用于定义内存屏障,避免代码重排序

  • loadFence() 表示该方法之前的所有load操作在内存屏障之前完成
  • storeFence()表示该方法之前的所有store操作在内存屏障之前完成
  • fullFence()表示该方法之前的所有load、store操作在内存屏障之前完成
posted @ 2021-02-22 18:58  BigBender  阅读(114)  评论(0编辑  收藏  举报