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

如何创建一家公司/windows优化大师是哪个公司的

如何创建一家公司,windows优化大师是哪个公司的,爱站seo工具包,wordpress评论 ajax目录 一,统计案例 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.whsansanxincailiao.cn/news/30719586.html

相关文章:

  • 为什么要做网站/网站入口
  • 网站建设方案申请/小程序开发需要哪些技术
  • 做网站用c 还是java/怎样注册网站
  • 网站的关键词排名靠前/下载官方正版百度
  • logo一键生成器哪个好/上海网站seo
  • 郑州网站建设/中公教育培训机构官网
  • 给期货交易类做网站违法吗/金泉网做网站多少钱
  • 应用商店下载安装打开/网站搜索引擎优化案例
  • 免费炫酷网站模板/深圳百度推广代理
  • 公司名称 网站域名 关联/seo外包服务专家
  • 武汉做网站哪家公司好/seo营销名词解释
  • 创建手机网页/中国十大seo
  • 遵义 网站建设/国内免费建网站
  • 宁夏网站设计/手机网站百度关键词排名查询
  • 在线设计平台优缺点/南京seo建站
  • 广州做响应式网站/永久免费二级域名申请
  • 苏州企业网站建设定制/销售渠道
  • 网吧设计装饰公司/宁波seo排名外包
  • 国外外贸论坛/seo草根博客
  • 建设网站com/深圳网站优化哪家好
  • 创业平台网站/seo在哪学
  • 做网站前期框架图/临沂色度广告有限公司
  • 政府网站建设集约化服务器/今天《新闻联播》回放
  • 做软装的网站/营销型网站建设总结
  • 维护一个网站难吗/超级seo外链
  • 公司网站自己可以做吗/上海搜索优化推广哪家强
  • 三河市网站建设/360网站推广
  • 龙岗英文网站制作/网址缩短在线生成器
  • 做网站的日历图片/整站优化的公司
  • 咸阳专业网站建设/推广网站有效的免费方法