java IO操作和计算操作:工作内存和主内存 volatile关键字作用;原子操作对象AtomicInteger ....
应该停止但无法停止的计算线程
如下线程示例,线程实例中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
posted on 2021-04-22 22:57 zhangmingda 阅读(108) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-04-22 深入理解css中position属性及z-index属性 https://www.cnblogs.com/zhuzhenwei918/p/6112034.html