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

如下线程示例,线程实例中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. es基本概念

    电商实时数据分析平台需要学些什么?  [运营指标,流量指标,销售转化指标,客户价值指标,商品指标,营销指标,风险控制指标,市场竞争指标]等电商指标数据. 检索,数据更新,排序,分词,query等缓存机 ...

  2. 查询多个count展示结果

    <select id="getCountByDISC" resultType="com.rm.algo.entity.AlgoResult"> SE ...

  3. Kubernetes(K8s)极速入门

    1. 概述 老话说的好:努力学习,努力提高,做一个有真才实学的人. 言归正传,之前我们聊了 如何使用国内的镜像源搭建 kubernetes(k8s)集群 ,今天我们来聊聊如何在 kubernetes( ...

  4. java番外茶余饭后闲聊

    java番外茶余饭后闲聊 **本人博客网站 **IT小神 www.itxiaoshen.com 今天聊点题外话没事时可以作为平时沟通交流的谈资,接下来一起简单了解下个人知晓对Java界开发产生深远影响 ...

  5. jQuery源码中的赌博网站

    前言 jQuery源码中有赌博网站? 起因是公司发的一份自查文件,某银行在日常安全运营过程中发现在部分jQuery源码中存在赌博和黄色网站链接. 链接分为好几个: www.cactussoft.cn ...

  6. Codeforces 1542E2 - Abnormal Permutation Pairs (hard version)(DP)

    upd on 2021.7.7:修了个 typo Codeforces 题目传送门 & 洛谷题目传送门 首先考虑怎样处理"字典序小"这个问题,按照字典序比大小的套路,我们可 ...

  7. DirectX12 3D 游戏开发与实战第十章内容(上)

    仅供个人学习使用,请勿转载.谢谢! 10.混合 本章将研究混合技术,混合技术可以让我们将当前需要光栅化的像素(也称为源像素)和之前已经光栅化到后台缓冲区的像素(也称为目标像素)进行融合.因此,该技术可 ...

  8. 【MetDNA】基于代谢反应网络的大规模代谢物结构鉴定新算法

    代谢是生命体内化学反应的总称,其所包含的代谢物变化规律可直接反映生命体的健康状态.非靶向代谢组学(untargeted metabolomics)可以在系统水平测量生命体内生理或病理状态下所有代谢物的 ...

  9. GIFS服务的使用

    1.安装Samba服务 登录192.168.200.20虚拟机,首先修改主机名,命令如下: [root@nfs-client ~]# hostnamectl set-hostname samba [r ...

  10. 05 Windows安装python3.6.4+pycharm环境

    windows安装python3.6.4环境 使用微信扫码关注微信公众号,并回复:"Python工具包",免费获取下载链接! 一.卸载python环境 卸载以下软件: 二.安装py ...