有什么网站可以免费搭建网址,社群营销怎么做,临沂哪家做网站最好,wordpress调用函数目录 一、什么是线程安全#xff1f; 二、线程不安全的原因 1、线程调度是随机的 2、修改共享数据#xff1a;多个线程修改同⼀个变量 3、原⼦性 编辑 #xff08;1#xff09;什么是原⼦性 #xff08;2#xff09;⼀条 java 语句不⼀定是原⼦的#xff0c;也不⼀定… 目录 一、什么是线程安全 二、线程不安全的原因 1、线程调度是随机的 2、修改共享数据多个线程修改同⼀个变量 3、原⼦性 编辑 1什么是原⼦性 2⼀条 java 语句不⼀定是原⼦的也不⼀定只是⼀条指令 3不保证原⼦性会给多线程带来什么问题 4可⻅性可⻅性指, ⼀个线程对共享变量值的修改能够及时地被其他线程看到. 5Java 内存模型 (JMM) 1) 初始情况下, 两个线程的⼯作内存内容⼀致. 编辑 2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步. 此时引⼊了两个问题: 1) 为啥整这么多内存? 2) 为啥要这么⿇烦的拷来拷去? 4、指令重排序 引言 在 Java 编程中线程安全是一个至关重要的概念。当多个线程同时访问共享的资源时如果没有适当的同步措施就会出现数据竞争和不一致的情况从而导致程序出现各种难以预料的错误。因此理解并处理线程安全问题是编写高质量、可靠性强的 Java 程序的关键。 一、什么是线程安全 线程安全是指在多线程环境中对共享资源的访问不会导致数据的损坏或不一致。一个线程安全的程序在多线程环境下执行时能够确保各个线程都能正确地操作共享的数据而不会产生意外结果。 二、线程不安全的原因
1、线程调度是随机的 这是线程安全问题的 罪魁祸⾸ 随机调度使⼀个程序在多线程环境下, 执⾏顺序存在很多的变数. 程序猿必须保证 在任意执⾏顺序下 , 代码都能正常⼯作. 2、修改共享数据多个线程修改同⼀个变量
3、原⼦性
1什么是原⼦性 我们把⼀段代码想象成⼀个房间每个线程就是要进⼊这个房间的⼈。如果没有任何机制保证A进⼊ 房间之后还没有出来B 是不是也可以进⼊房间打断 A 在房间⾥的隐私。这个就是不具备原⼦性 的。 那我们应该如何解决这个问题呢是不是只要给房间加⼀把锁A 进去就把⻔锁上其他⼈是不是就进不来了。这样就保证了这段代码的原⼦性了。 有时也把这个现象叫做同步互斥表⽰操作是互相排斥的。 2⼀条 java 语句不⼀定是原⼦的也不⼀定只是⼀条指令 ⽐如刚才我们看到的 n其实是由三步操作组成的 从内存把数据读到 CPU 进⾏数据更新 把数据写回到 CPU
3不保证原⼦性会给多线程带来什么问题 如果⼀个线程正在对⼀个变量操作中途其他线程插⼊进来了如果这个操作被打断了结果就可能是错误的。 这点也和线程的抢占式调度密切相关. 如果线程不是 抢占 的, 就算没有原⼦性, 也问题不⼤. 4可⻅性可⻅性指, ⼀个线程对共享变量值的修改能够及时地被其他线程看到.
5Java 内存模型 (JMM) Java虚拟机规范中定义了Java内存模型. ⽬的是屏蔽掉各种硬件和操作系统的内存访问差异以实现让Java程序在各种平台下都能达到⼀致的并发效果. 线程之间的共享变量存在 主内存 (Main Memory). 每⼀个线程都有⾃⼰的 ⼯作内存 (Working Memory) . 当线程要读取⼀个共享变量的时候, 会先把变量从主内存拷⻉到⼯作内存, 再从⼯作内存读取数据当线程要修改⼀个共享变量的时候, 也会先修改⼯作内存中的副本, 再同步回主内存. 由于每个线程有⾃⼰的⼯作内存, 这些⼯作内存中的内容相当于同⼀个共享变量的 副本. 此时修改线程1 的⼯作内存中的值, 线程2 的⼯作内存不⼀定会及时变化 1) 初始情况下, 两个线程的⼯作内存内容⼀致. 2) ⼀旦线程1 修改了 a 的值, 此时主内存不⼀定能及时同步. 对应的线程2 的⼯作内存的 a 的值也不⼀定能及时同步. 这个时候代码中就容易出现问题.
此时引⼊了两个问题:
为啥要整这么多内存? 为啥要这么⿇烦的拷来拷去?
1) 为啥整这么多内存? 实际并没有这么多 内存. 这只是 Java 规范中的⼀个术语, 是属于 抽象 的叫法. 所谓的 主内存 才是真正硬件⻆度的 内存. ⽽所谓的 ⼯作内存, 则是指 CPU 的寄存器和⾼速缓存. 2) 为啥要这么⿇烦的拷来拷去? 因为 CPU 访问⾃⾝寄存器的速度以及⾼速缓存的速度, 远远超过访问内存的速度(快了 3 - 4 个数量级, 也就是⼏千倍, 上万倍). ⽐如某个代码中要连续 10 次读取某个变量的值, 如果 10 次都从内存读, 速度是很慢的. 但是如果只是 第⼀次从内存读, 读到的结果缓存到 CPU 的某个寄存器中, 那么后 9 次读数据就不必直接访问内存了. 效率就⼤⼤提⾼了. 那么接下来问题⼜来了, 既然访问寄存器速度这么快, 还要内存⼲啥?? 答案就是⼀个字: 贵 值的⼀提的是, 快和慢都是相对的. CPU 访问寄存器速度远远快于内存, 但是内存的访问速度⼜远远快 于硬盘. 对应的, CPU 的价格最贵, 内存次之, 硬盘最便宜 4、指令重排序 什么是代码重排序 ⼀段代码是这样的 去前台取下 U 盘 去教室写 10 分钟作业 去前台取下快递 如果是在单线程情况下JVM、CPU指令集会对其进⾏优化⽐如按 1-3-2的⽅式执⾏也是没问题可以少跑⼀次前台。这种叫做指令重排序 编译器对于指令重排序的前提是 保持逻辑不发⽣变化. 这⼀点在单线程环境下⽐较容易判断, 但是在多线程环境下就没那么容易了, 多线程的代码执⾏复杂程度更⾼, 编译器很难在编译阶段对代码的执⾏效果进⾏预测, 因此激进的重排序很容易导致优化后的逻辑和之前不等价. 总结 在编写 Java 程序时必须时刻牢记线程安全问题合理使用同步机制、并发容器和原子类等工具确保多线程环境下程序的正确性和稳定性。只有这样才能编写出高效、健壮的多线程应用。