为什么会产生线程安全问题之不可见性

Java内存模型

    网上好多文章再讲到java内存模型时都讲方法区,堆栈等内容,我个人认为这属于jvm内存结构,我认为jmm指的是这个(如图)
java内存模型

    当我们的类中存在共享变量(如全局静态变量)这些共享变量将放到java内存模型的主内存中去。

线程更改共享变量值过程

1.线程读取共享变量到自己的副本中
2.更改副本的值
3.刷新到主内存

线程间通讯

什么是线程间通讯

    通俗的说就是当A线程将变量b的值更改了,线程B需要知道A将变量b改成了什么,线程B如何能够知道就是线程间如何通讯 。

线程间如何通讯

    当线程A更改完成后,并且将更改后的值刷新到了主内存,线程B从主内存中读取了新值,这就完成了线程A,B间的通讯

线程不可见

    当线程A将变量b的值更改之后还没来得及刷新到主内存,这时候CPU将执行权交给了线程B,线程B拿着线程A修改之前的变量b去做相应的操作,可能运行的结果并不是你所要的,这就叫做线程不可见性
不可见性图解

不可见例子

(这个例子比较容易演示出线程安全问题)

package com.demo.thread;

public class ThreadDemo {
	
	
	public static void main(String[] args) throws InterruptedException {
		
		Thread threadA = new Thread(new ThreadA());
		threadA.start();
		Thread.sleep(100);
		ThreadA.flag = false;
		System.out.println("flag已设为false");
	}


	
}

/**
 * 线程A
 * @author Administrator
 *
 */
class ThreadA implements Runnable{
	
	public static boolean flag = true;
	
	@Override
	public void run() {
		
		while(flag) {
						
		}
		System.out.println("线程A结束");		
		
	}
	
}



运行结果
不可见性演示
原因:主线程将flag设为false之后,由于jvm优化原因线程A仍读取的是自己的副本,所以一直在做while循环

解决办法

public volatile static boolean flag = true;**加粗样式**

在flag前加volatile关键字,这样线程读取时,会强制从主内存中读取

结果
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值