java多线程中如何保证变量的可见性、原子性

做过多线程开发的猿友们应该会遇到这两个问题

首先,理解一下可见性:

线程在修改主存变量的时候会先拷贝一份到自己的线程栈中去处理,每个线程都有自己的空间,相互是独立的,在变量修改完成到写入主存中,这个过程对其它线程是不可见的。(这里不明白的话可以看一下java内存模型及线程间的通信)

那么问题来了 不可见会如何?数据的一致性会被打乱,程序出bug,A线程改了变量c的值,B线程读到的却是c原来的值(其实想要的是A线程改后的值)

解决办法:

使用synchronized(低效,使用悲观锁)、volatile修饰符来保证变量的可见性

Jdk5后提出了atomic 原子操作也可以保证可见性(高效且不需要使用同步,基于CAS)

Volatilesynchronized区别

Volatile只是保证变量可见性,并不能确保原子性,它是依赖CPU提供的特殊指令内存屏障指令来控制可见性,被Volatile修饰的成员变量在被线程访问时在读操作前会强行插入一条内存屏障读指令强行从主存中读取(让高速缓存中的数据失效,重新从主内存加载数据),变量在被线程修改时会在写指令之后插入写屏障让写入缓存的最新数据写回到主内存

不能确保原子性,是因为如果A线程和B线程同时读取到变量a值,A线程修改a后将值刷到主存、同时B线程也修改了a的值并刷到主存,这时候B线程就覆盖了A线程修改操作。

Synchronized是通过对线程加锁(独占锁)控制线程同步,被Synchronized修饰的内存只允许一个线程访问

Cas理解(乐观锁基于CAS

3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做,重新再尝试。注意ABA情况



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页