应该停止但无法停止的计算线程

如下线程示例,线程实例中while循环中的条件,在主线程中通过调用实例方法更新后,while循环并没有更新判断变量是否还成立。而是陷入了while(true)死循环.

import javafx.scene.paint.Stop;

/**
* @ClassName ThreadMemoryModeStopFailed
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/22.
*/
public class ThreadMemoryModeStopFailed {
private static long num = 0;
private static class StopFailed implements Runnable{
private boolean shouldSTop = false; public void setShouldSTop(boolean shouldSTop) {
this.shouldSTop = shouldSTop;
} @Override
public void run() {
while (!shouldSTop){
//当注释掉IO操作System.out.println 后,就会一直卡在num++一直算不会停止
// System.out.println(Thread.currentThread().getName() + "当前时间戳"+ System.currentTimeMillis());
num++;
}
System.out.println("运行结束");
}
}
public static void main(String[] args) throws InterruptedException {
StopFailed sr = new StopFailed();
Thread thread = new Thread(sr);
thread.start();
Thread.sleep(1000);
sr.setShouldSTop(true);
System.out.println("num结果:" + num);
}
}
上面的代码,如果在while循环中,我们加入了一行System.out.println之后,逻辑是正常的,线程可以被停止,但是如果注释了System.out.println之后,我们仅仅保留num++,这个时候我们的程序逻辑不正常了,一直陷入while死循环计算中。没有重新读取修改后的shouldSTop变量

java的内存模型

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
当子线程非常消耗CPU的时候,子线程的工作内存不会主动去和主内存中的共享变量同步这个就造成了我们刚刚出现的问题。但是当CPU消耗不是太厉害的时候,JVM会自动的把主内存中的共享变量同步到线程的工作内存中。
JVM有两种启动启动模式:
一种是client启动模式,还有之中是server启动模式。server模式启动比较慢,但是启动了之后程序的运行速度比较快,这个是因为Server模式在内存方面做优化就是上面的cache。client模式启动的时候比较快,内存使用比较少,但是程序运行的速度就比较慢

1、volatile关键字解决

volatile关键字解决工作内存和主内存变量不同步问题

private static volatile long num = 0;
我们发现子线程被停止了。这个是为什呢?volatile的作用,就是告诉我们的子线程,你在读取变量的时候,直接去主内存中读取,不要在工作内存中读取。

2、原子性操作对象,避免并发线程操作同一个对象值覆盖

volatile 关键字无法解决多线程操作同一个对象的原子性问题。原子性变量AtomicInteger 替代Integer 可以避免计算冲突错误,多线程操作此变量变为串行效果。 

示例:

import java.util.concurrent.atomic.AtomicInteger;

/**
* @ClassName ThreadMemoryModeVolatileNotSafe
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/23.
*/
public class ThreadMemoryModeVolatileNotSafe {
// private static volatile int num = 0; //非原子性变量
private static volatile AtomicInteger num = new AtomicInteger(0); //原子性变量 public static void main(String[] args) {
Runnable r = ()->{
for(int i=0; i< 1000; i++){
// num ++; //非原子性变量
num.addAndGet(1); //原子性整数自加一
}
};
for(int j=0; j<10; j++){
new Thread(r,"T"+j).start();
} try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " num:" + num);
/**
* 非原子性变量结果:不定
* 原子性变量结果:10000 反复测试符合预期
*/
}
}

java IO操作和计算操作:工作内存和主内存 volatile关键字作用;原子操作对象AtomicInteger ....的更多相关文章

  1. java线程内存模型,线程、工作内存、主内存

    转自:http://rainyear.iteye.com/blog/1734311 java线程内存模型 线程.工作内存.主内存三者之间的交互关系图: key edeas 所有线程共享主内存 每个线程 ...

  2. Java线程工作内存与主内存变量交换过程及volatile关键字理解

    Java线程工作内存与主内存变量交换过程及volatile关键字理解 1. Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行.此处的所谓内存模 ...

  3. Java内存模型与volatile关键字

    Java内存模型与volatile关键字 一).并发程序开发 并行程序的开发要涉及多线程.多任务间的协作和数据共享问题. 常用的并发控制:内部锁.重入锁.读写锁.信号量. 二).线程的特点 线程的特点 ...

  4. java volatile关键字作用及使用场景

    1. volatile关键字的作用:保证了变量的可见性(visibility).被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象.如以下代码片段,isShut ...

  5. java io流 对文件操作

    检查文件是否存在 获取文件路径 获取文件大小 ...... 更多参考手册 //对文件的操作 //检查文件是否存在 //获取文件路径 //获取文件大小 //文件是否可读 //文件是否可写 //.... ...

  6. java IO流 对文件操作的代码集合

    Io流 按照分类 有两种分类 流向方向: 有输入流和输出流 按照操作类型有:字节流和字符流 按照流向方向 字节流的一些操作 //读文件 FileInputStream fis = new FileIn ...

  7. java IO流 Zip文件操作

    一.简介 压缩流操作主要的三个类 ZipOutputStream.ZipFile.ZipInputStream ,经常可以看到各种压缩文件:zip.jar.GZ格式的压缩文件 二.ZipEntry   ...

  8. Java IO编程——File文件操作类

    在Java语言里面提供有对于文件操作系统操作的支持,而这个支持就在java.io.File类中进行了定义,也就是说在整个java.io包里面,File类是唯一 一个与文件本身操作(创建.删除.重命名等 ...

  9. Java IO基础--File常用操作(递归)

    File中经常会使用递归方法打印属性结构.统计文件夹下文件个数.子文件夹个数以及文件大小,可以作为递归的应用练习. 递归的写法,百度一搜一大堆,这里我使用对javabean方式封装了一下: packa ...

随机推荐

  1. 既生瑜何生亮 access_token VS refresh_token

    中国有句老话, 既生瑜何生亮, 既然有我周瑜在世, 为什么老天还要一个诸葛亮啊? 同样的, 众所周知, 在 OAuth 2.0 授权协议中, 也有两个令牌 token , 分别是 access_tok ...

  2. JavaScript中的多种进制与进制转换

    进制介绍 JavaScript 中提供的进制表示方法有四种:十进制.二进制.十六进制.八进制. 对于数值字面量,主要使用不同的前缀来区分: 十进制(Decimal): 取值数字 0-9:不用前缀. 二 ...

  3. 解决ip和域名都能够ping通但是启动nginx无法访问网页的问题

    解决思路 最近双11逛西部数码的官网看看有没有什么服务器优惠的时候,发现了可以申请一个一块钱用一整年的SSL证书,立马心动下单了,想想俺也可以用https装装X了哈哈 不过在部署完证书,并调整ngin ...

  4. Codeforces 566C - Logistical Questions(点分治)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%% 首先考虑对这个奇奇怪怪的 \(t^{3/2}\) 进行一番观察.考虑构造函数 \(f(x)=ax^{3/2}+b(d-x) ...

  5. Codeforces 1396D - Rainbow Rectangles(扫描线+线段树)

    Codeforces 题面传送门 & 洛谷题面传送门 一道鸽了整整一年的题目,上一次提交好像是 2020 年 9 月 13 日来着的(?) 乍一看以为第 2 个提交和第 3 个提交只差了 43 ...

  6. 标准非STL容器 : bitset

    1. 概念 什么是"标准非STL容器"?标准非STL容器是指"可以认为它们是容器,但是他们并不满足STL容器的所有要求".前文提到的容器适配器stack.que ...

  7. 前后端分离进阶一:使用ElementUI+前端分页

    前两篇入门:前后端分离初体验一:前端环境搭建 前后端分离初体验二:后端环境搭建+数据交互 参考:https://www.bilibili.com/video/BV137411B7vB B站UP:楠哥教 ...

  8. 入坑不亏!我们最终决定将 70w+ 核心代码全部开源

    作者 | 一啸 来源 | 尔达 Erda 公众号 背景故事 2017 年初,我们基于 DC/OS (mesos + marathon) 开始构建端点自己的 PaaS 平台,核心任务就是解决公司的软件开 ...

  9. 11. 关于WIN7 64位系统安装ADS的种种意外情况解决方法

    安装ADS的环境,以前安装过,觉得应该可以安装呀,没想到,装不上,安装不成功,后来花费好长时间,终于把他装好了,费时费力呀. 特此记录一下,以戒后人.大家安装问题建议整篇看完,再去安装,以防一个问题解 ...

  10. Flink(三)【核心编程】

    目录 一.Environment 二.Source 从集合读取数据 从文件读取数据 从kakfa读取数据(常用) 自定义数据源 三.Transform map Rich版本函数 flatMap key ...