当前位置: 首页 > wzjs >正文

建设有限公司网站检查网站的跳转路径是否清晰 哪里要优化

建设有限公司网站,检查网站的跳转路径是否清晰 哪里要优化,丽水市龙泉市网站建设公司,安阳建筑设计目录 一,统计案例 1.1 原生代码 1.2 追加volatile关键字 1.3 追加 synchronized 关键字 二,总结 2.1 关键字总结 2.2 原子性,可见性,有序性 2.3【总结】 三,系列文章推荐 一,统计案例 在上一章…

目录

一,统计案例

1.1 原生代码

1.2 追加volatile关键字

1.3 追加 synchronized 关键字

二,总结

2.1 关键字总结

2.2 原子性,可见性,有序性

2.3【总结】

三,系列文章推荐


一,统计案例   

         在上一章《多线程基础讲解》中提到多线程的基础使用,生命周期,常用API等基本使用的知识点。并且我们可以体会到每个子任务可以交给不同的线程执行,实现真正的“分而治之”。

        在多线程进行任务分批处理的时候。如何做到资源在实时更新的同时也能被其他线程及时感知到。多线程在资源共享与资源竞争提供哪些机制确保数据的一致性。通过一个案例讲解。

1.1 原生代码

/*** @author toast* @time 2025/3/19* @remark*/
class Counter {private int count = 0;public void increment() {count++; // 不是原子操作}public int getCount() {return count;}
}public class RaceConditionExample {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();// 创建两个线程同时修改 count 变量追加10000次Thread t1 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T1执行完毕");});Thread t2 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T2执行完毕");});t1.start();t2.start();t1.join(); // main主线程等待t1线程执行完毕t2.join(); // main主线程等待t2线程执行完毕System.out.println("最终 count 值:" + counter.getCount());}
}

输出结果:

T2执行完毕
T1执行完毕
最终 count 值:17829

        输出结果并非20000。而是一个 17829。这是为什么?我们可以先讲一下这个赋值过程我们就知道了。

        从统计算计的赋值流程,我们可以了解到线程T1,T2分别先从主内存(Main memory)读取 count = 10; 之后又各自运行各自的统计业务。在这过程之中线程之间的工作内存又是不共享,相当于两个线程同时读取 10 并执行 +1,最终 count 只增加了一次,变成 11❌。

1.2 追加volatile关键字

        在1.1 的案例当中,我们发现线程每一次都需要进行从主内存进行一次数据读取到线程的工作内存之中,现在通过 volatile 关键字,让其线程直接使用主内存(Main momery)的数据。代码如下

package com.toast.javase.source.thread;import java.util.stream.IntStream;/*** @author toast* @time 2025/3/19* @remark*/
class VolatileCounter {private volatile int count = 0;public void increment() {count++; // 仍然不是原子操作}public int getCount() {return count;}
}public class VolatileExample {public static void main(String[] args) throws InterruptedException {VolatileCounter counter = new VolatileCounter();Thread t1 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T1执行完毕");});Thread t2 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T2执行完毕");});t1.start();t2.start();t1.join();t2.join();System.out.println("最终 count 值:" + counter.getCount());}
}

输出结果

T1执行完毕
T2执行完毕
最终 count 值:18499

        现在追加了 volatile 关键字,使其线程之间的count是可见的,就算数据修改了,其他线程也是可以感知到了。但是为什么还不是 20000?观察如下示意图

        count 追加了 volatile 关键字,确实实现了线程之间的数据可见性,但没有解决count数据覆盖导致统计失败。其原因就是T1, T2 在争抢资源的时候没有一个界限。按道理第二次计算,不管是T1执行第二次计算,还是T2执行第二次计算,其读取到的值应该是count = 11; 而非 count = 10;

        而这个界限,或者说临界点的开放与关闭在 JVM里面提供一个关键字,这个关键字就是synchronized,也被称为“内置锁”( Intrinsic Lock )。

1.3 追加 synchronized 关键字

package com.toast.javase.source.thread;import java.util.stream.IntStream;/*** @author liuwq* @time 2025/3/19* @remark*/
class SynchronizedCounter {private volatile int count = 0;// 现在是线程安全的public synchronized void increment() {count++;}public int getCount() {return count;}
}public class SynchronizedExample {public static void main(String[] args) throws InterruptedException {SynchronizedCounter counter = new SynchronizedCounter();Thread t1 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T1执行完毕");});Thread t2 = new Thread(() -> {IntStream.range(0, 10000).forEach(i -> counter.increment());System.out.println("T2执行完毕");});t1.start();t2.start();t1.join();t2.join();System.out.println("最终 count 值:" + counter.getCount()); // 结果一定是 20000}
}

输出结果

T1执行完毕
T2执行完毕
最终 count 值:20000

        赋值流程图如下

二,总结

2.1 关键字总结

        从上面的统计案例当中,我们知道了关键字 volatile 以及 synchronized 关键字的作用。

volatile

作用一:保证了数据在线程之间的可见性,

作用二:防止CPU指令重排,上面案例并未明显体现

synchronized

作用一:保证了代码的互斥性,同一时间只允许一个线程执行。

作用二:保证了可见性,进入synchronized 代码之前,会从主内存读取数据,代码结束,退出synchronized代码,必须回写数据到主 内存。(问大家一个问题,如果数据没有 volatile 关键字修饰,还会从主内存读取数据吗?当然会了,只不过是读取完之后存储在自己的工作内存空间里,计算完再回写过去。只不过整个过程数据没有可见性)

作用三:保证了原子性,其代码内的操作是不可分割的

2.2 原子性,可见性,有序性

        其实在上面的 2.1 关键字总结上就已经总结出来了原子性,可见性(数据可见性),以及有序性

原子性

原子性,顾名思义,借用“原子”不可分割的性质。表示 一个操作要么全部执行成功,要么全部失败,不能被其他线程打断

可见性

可见性表示数据在线程之间是否可见,在修改变量数据时其他线程是否能感知到

有序性

有序性指的是程序执行的顺序符合代码编写的逻辑顺序,但由于 JVM JIT 编译器优化、CPU 指令重排(Instruction Reordering),实际执行顺序可能不同。

2.3【总结】

        对于保证原子性,JVM提供内置锁 synchronized 关键字,以及JDK1.5之后的Lock 接口。

        对于可见性,提供volatile 关键字,确保数据在线程之间的可见性

        对于有序性,也是 volatile 通过禁止 指令重排 来确保有序性。指令重排是 CPU 为提高性能而对程序指令执行顺序进行调整的技术。指令重排可能会导致线程看到不一致的状态,从而产生竞态条件。

  

        

三,系列文章推荐

        最后,如果这篇文章对你有帮助,欢迎 点赞👍、收藏📌、关注👀
        我会持续分享 Java、Spring Boot、MyBatis-Plus、微服务架构 相关的实战经验,记得关注,第一时间获取最新文章!🚀

        这篇文章是 【Java SE 17源码】系列 的一部分,详细地址:

java SE 17 源码篇_吐司呐的博客-CSDN博客

        记得 关注我,后续还会更新更多高质量技术文章!

你在实际开发中遇到过类似的问题吗?
欢迎在评论区留言交流,一起探讨 Java 开发的最佳实践! 🚀

http://www.dtcms.com/wzjs/590647.html

相关文章:

  • 免费红色ppt模板网站广州品牌策划有限公司
  • 鄂州网站制作企业新手怎么做网站内容维护
  • 榆林网站开发大连手机自适应网站制作公司
  • 网站备案需要哪些材料网站收录和没收录区别
  • 网页设计实训报告工作内容和步骤seo属于运营还是技术
  • 网站seo推广优化报价表网站建设满意度问卷调查
  • 建设网站比较好网站设计确认书
  • 福建有没有网站做鞋子一件代发qq官网登录
  • 做新闻微网站有哪些方面现在去横琴会变黄码吗
  • 贵阳做网站需要多少钱有哪些好的做问卷调查的网站好
  • 江西省美丽乡村建设公布网站网站换ip影响 百度
  • 北京建设教育协会的网站广州新业建设管理有限公司网站
  • 知名企业网站搭建新感觉全网价值营销服务商wordpress 搜索 提示
  • 灵感中心素材网站申请网站域名多少钱
  • 中国做的比较好的网站设计公司有哪些帮别人做网站收多少钱合适
  • 做360手机网站优化快苏州诗华洛网站建设
  • 一级a做爰片免费网站孕交视频app制作软件手机版免费下载
  • 做网站公司选哪家在线图片编辑器图怪兽
  • 河北工程大学网站开发成本网络营销推广案例
  • 有没有专门做游戏人物的绅士视频网站怎么夸一个网站开发公司
  • 公司的网站建设计入什么科目wordpress游客发言
  • 长沙县不错的建站按效果付费网页设计代码单词
  • 上海网站制作团队服务好的网站建设平台
  • 西安网站制作公司有哪家wordpress默认中文
  • 做网站 以图搜货检测WordPress网站的安全性
  • 南昌网站建设索王道下拉网页生成pdf不显示
  • 电脑如何建立网站网站可兼容移动端
  • 军用棉被门网站建设企业网站优化的原则
  • 织梦确定网站风格wordpress 增加语言包
  • 做网站的计划书个人网站建设在哪里