网站和网页不同吗,开发手机软件,一流的菏泽网站建设,微信公众平台内做网站一、多线程产生安全问题
1、Java内存模型 共享内存模型指的就是Java内存模型(简称JMM)#xff0c;JMM决定一个线程对共享变量的写入时,能对另一个线程可见。
从抽象的角度来看#xff0c;JMM定义了线程和主内存之间的抽象关系#xff1a;
线程之间的共享变量存储在主内存…一、多线程产生安全问题
1、Java内存模型 共享内存模型指的就是Java内存模型(简称JMM)JMM决定一个线程对共享变量的写入时,能对另一个线程可见。
从抽象的角度来看JMM定义了线程和主内存之间的抽象关系
线程之间的共享变量存储在主内存(main memory)中每个线程都有一个私有的本地内存(local memory)本地内存中存储了该线程以读/写共享变量的副本。
本地内存是JMM的一个抽象概念并不真实存在。它涵盖了缓存写缓冲区寄存器以及其他的硬件和编译器优化。
1.主内存存放多线程操作的共享变量 比如count0
2.本地内存存储了当前该线程以读/写共享变量的副本副本 count10count20 多线程同时进行变量操作时比如对count进行先对副本进行为1将副本刷新到主内存由于两个线程是不可见的共享变量变为1理论为2但是还是1
2.不可见 3.可见性
线程A与线程B之间如要通信的话必须要经历下面2个步骤 首先线程A把本地内存A中更新过的共享变量刷新到主内存中去。 然后线程B到主内存中去读取线程A之前已更新过的共享变量。
下面通过示意图来说明这两个步骤 二、Volatile
什么是Volatile
可见性也就是说一旦某个线程修改了该被volatile修饰的变量它会保证修改的值会立即被更新到主存当有其他线程需要读取时可以立即获取修改之后的值。
在Java中为了加快程序的运行效率对一些变量的操作通常是在该线程的寄存器或是CPU缓存上进行的之后才会同步到主存中而加了volatile修饰符的变量则是直接读写主存。
Volatile 保证了线程间共享变量的及时可见性但不能保证原子性
class ThreadVolatileDemo extends Thread {public boolean flag true;Overridepublic void run() {undefinedSystem.out.println(开始执行子线程....);while (flag) {undefined}System.out.println(线程停止);}public void setRuning(boolean flag) {this.flag flag;}}public class ThreadVolatile {public static void main(String[] args) throws InterruptedException {ThreadVolatileDemo threadVolatileDemo new ThreadVolatileDemo();threadVolatileDemo.start();Thread.sleep(3000);threadVolatileDemo.setRuning(false);System.out.println(flag 已经设置成false);Thread.sleep(1000);System.out.println(threadVolatileDemo.flag);}}运行结果:
已经将结果设置为fasle为什么还一直在运行呢。
原因:线程之间是不可见的读取的是副本没有及时读取到主内存结果。
解决办法使用Volatile关键字将解决线程之间可见性, 强制线程每次读取该值的时候都去“主内存”中取值
2、Volatile特性
1.保证此变量对所有的线程的可见性这里的“可见性”如本文开头所述当一个线程修改了这个变量的值volatile 保证了新值能立即同步到主内存以及每次使用前立即从主内存刷新。但普通变量做不到这点普通变量的值在线程间传递均需要通过主内存(详见Java内存模型)来完成。
2.禁止指令重排序优化。有volatile修饰的变量赋值后多执行了一个“load addl $0x0, (%esp)”操作这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置)只有一个CPU访问内存时并不需要内存屏障(什么是指令重排序是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。
volatile 性能
volatile 的读性能消耗与普通变量几乎相同但是写操作稍慢因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。
(1)从而我们可以看出volatile虽然具有可见性但是并不能保证原子性。
(2)性能方面synchronized关键字是防止多个线程同时执行一段代码就会影响程序执行效率而volatile关键字在某些情况下性能要优于synchronized。
但是要注意volatile关键字是无法替代synchronized关键字的因为volatile关键字无法保证操作的原子性。