淘宝你都会淘些啥?我淘了些并发知识的图片你要不要?

 

1、读改写操作就不是原子的情况,

举个例子:如果i=1,我们进行两次i++操作,我们期望的结果是3,但是有可能结果是2。如下图

 

 

 2.unsafe

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。

Unsafe类为一单例实现,提供静态方法getUnsafe获取Unsafe实例,当且仅当调用getUnsafe方法的类为引导类加载器所加载时才合法,否则抛出SecurityException异常。 

 

 3.DirectByteBuffer

DirectByteBuffer是Java用于实现堆外内存的一个重要类,通常用在通信过程中做缓冲池,如在Netty、MINA等NIO框架中应用广泛。
DirectByteBuffer对于堆外内存的创建、使用、销毁等逻辑均由Unsafe提供的堆外内存API来实现。
下图为DirectByteBuffer构造函数,创建DirectByteBuffer的时候,通过Unsafe.allocateMemory分配内存、Unsafe.setMemory进行内存初始化,而后构建Cleaner对象用于跟踪DirectByteBuffer对象的垃圾回收,以实现当DirectByteBuffer被垃
圾回收时,分配的堆外内存一起被释放。 

 

4.AtomicInteger中CAS的实现基础

如下图所示,AtomicInteger的实现中,静态字段valueOffset即为字段value的内存偏移地址,valueOffset的值在AtomicInteger初始化时,在静态代码块中通过Unsafe的objectFieldOffset方法获取。
在AtomicInteger中提供的线程安全方法中,通过字段valueOffset的值可以定位到AtomicInteger对象中value的内存地址,从而可以根据CAS实现对value字段的原子操作

 

5.AtomicInteger中CAS的应用举例

下图为某个AtomicInteger对象自增操作前后的内存示意图,对象的基地址baseAddress=“0x110000”,通过baseAddress+valueOffset得到value的内存地址valueAddress=“0x11000c”;
然后通过CAS进行原子性的更新操作,成功则返回,否则继续重试,直到更新成功为止。

 

6.StampedLock

在Java 8中引入了一种锁的新机制——StampedLock,它可以看成是读写锁的一个改进版本。
StampedLock提供了一种乐观读锁的实现,这种乐观读锁类似于无锁的操作,完全不会阻塞写线程获取写锁,从而缓解读多写少时写线程“饥饿”现象。
由于StampedLock提供的乐观读锁不阻塞写线程获取读锁,当线程共享变量从主内存load到线程工作内存时,会存在数据不一致问题,所以当使用StampedLock的乐观读锁时,需要遵从如下图用例中使用的模式来确保数据的一致性

 

7.StampedLock.validate方法中内存屏障的使用

下图为StampedLock.validate方法的源码实现,通过锁标记与相关常量进行位运算、比较来校验锁状态,在校验逻辑之前,会通过Unsafe的loadFence方法加入一个load内存屏障,目的是避免上图👆用例中步骤②和StampedLock.validate中锁状态校验运算发生重排序导致锁状态校验不准确的问题

 

 

 

posted @ 2020-10-28 18:35  powerZhangFly  阅读(96)  评论(0)    收藏  举报