多线程-volatile

volatile主要用途

1、保证可见性
	对volatile变量的写指令后会加入写屏障
		写屏障:在屏障之前的对共享变量的改动都同步到主存
	对volatile变量的读指令前会加入读屏障
		读屏障:在该屏障之后对共享变量的读取加载的都是主存中的新数据
2、保证有序性
	写屏障保证指令重排序时,不会讲写屏障之前的代码派到写屏障之后
	读屏障保证指令重排序时,不会讲读屏障之后的代码排到读屏障之前

不能解决多个线程并发执行指令交错的问题

image
上面的代码中会有指令重排序的问题
对应的字节码文件
image

可能会被优化为先执行24(赋值),再执行21(调用对象的构造方法)

当线程A进入同步代码块时,先执行赋值操作,但是还没有调用对象的构造方法,此时线程b进入了方法,由于判断不为空会直接拿到还没有初始化完全的对象,从而产生问题

synchronized可以保证有序性,但是前提是需要将对象完全交给synchronized管理,在上面的代码中由于代码块中还有对 对象 的操作,所以会有问题
(CAS需要借助volatile才能读取到共享变量的最新值来实现【比较并交换】)

在AtomicInteger中 value 就被volatile修饰
image

原子引用:
利用CAS思想
AtomicReference

AtomicStampedReference 解决CAS产生的ABA问题 可以设置版本号

AtomicMarkableReference 用boolean 来表示是否被更改过

如果只是单纯的累加操作 LongAdder 的性能要比AtomicLong要更好,在有多个线程竞争时,设置多个累加单元cell[i](数量不会超过cpu核心数,只有cpu拥有多个核心数CAS才有意义),最后讲结果汇总。这样他们累加的时候操作的是不同的cell变量,减少了CAS重试失败。

posted @ 2022-03-17 15:05  原来是晴天啊  阅读(87)  评论(0)    收藏  举报