Java如何实现并发的原子性、可见性和有序性
2022/1/11 20:07:52
本文主要是介绍Java如何实现并发的原子性、可见性和有序性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
一、原子性
1、原子性原理
2、测试代码
二、可见性
1、可见性原理
2、测试代码
2.1、synchronized和lock也能实现可见性
2.2、添加volatile关键字也能实现可见性
三、有序性
1、有序性原理
2、测试代码
一、原子性
1、原子性原理
一个操作或者多个操作要么全部执行并且执行的过程不被任何因素打断,要么都不执行。
2、测试代码
按正常的运行结果来说它应该是20000,但运行结果却并不是,产生的原因是有几个线程点,两个线程都读完了然后进行加一操作,都赋值给a因此才导致只加了一次。
public class Test03 { public static int a=0; public static void main(String[] args) throws InterruptedException { for (int i=0;i<10000;i++){ new Thread(new Runnable() { @Override public void run() { a++; } }).start(); new Thread(new Runnable() { @Override public void run() { a++; } }).start(); } Thread.sleep(1000); System.out.println(a); } }
解决办法我们可以采用synchronized和Lock来实现,由于synchronized和Lock能够保证任意时刻只有一个线程执行该代码块,那么就保证了原子性。
二、可见性
1、可见性原理
可见性是指当多个线程访问同一个变量的时候,一个线程修改了这个变量的值,其他线程能够立即看到修改后的值。
2、测试代码
改代码会一直处于运行状态,因为其线程无法实现线程的同步,因为普通的共享变量是不能够保证可见性的,因为普通变量修改之后不知道何时会写入内存,因此很难实现可见性。
public class Test01 { private static boolean run=true; private static void test(){ System.out.println("start------"); while (run){ } System.out.println("end--------"); } public static void main(String[] args) throws InterruptedException { new Thread(Test01::test).start(); Thread.sleep(10000); run=false; } }
2.1、synchronized和lock也能实现可见性
在该线程的基础上添加了一个输出
public class Test01 { private static boolean run=true; private static void test(){ System.out.println("start------"); while (run){ System.out.println("hallo"); } System.out.println("end--------"); } public static void main(String[] args) throws InterruptedException { new Thread(Test01::test).start(); Thread.sleep(10000); run=false; } }
从结果可以看出它是实现可见性的,因为println里面是有synchronized,因为synchronized和locl也是能够保证可见性的,因为他们能够保证只有一个线程能够获取锁,并且在释放锁的时候能够实现将跟新的数据写入到内存当中。
2.2、添加volatile关键字也能实现可见性
public class Test01 { private static volatile boolean run=true; private static void test(){ System.out.println("start------"); while (run){ System.out.println("hallo"); } System.out.println("end--------"); } public static void main(String[] args) throws InterruptedException { new Thread(Test01::test).start(); Thread.sleep(10000); run=false; } }
volatile能够实现对该线程只有发生变化则会立即跟新到内存中,并且让其他线程能够及时可见。
三、有序性
1、有序性原理
有序性是指程序执行的顺序按照代码的先后顺序执行。
2、测试代码
该代码主要是当x=0和y=0时线程才会停止,因此从结果可以明白,在Java内存模型中,允许编译器和处理器对我们所编译的代码进行重排序但要保证其不会影响到最终的结果的正确性。因此下述代码并没有保证有序性。
public class Test02 { public static int x=0,y=0; public static int a=0,b=0; public static void main(String[] args) throws InterruptedException { for (long i=0;i<Long.MAX_VALUE;i++){ x=0;y=0;a=0;b=0; CountDownLatch latch = new CountDownLatch(2); Thread one = new Thread(new Runnable() { @Override public void run() { a=1; x=b; latch.countDown(); } }); Thread other = new Thread(new Runnable() { @Override public void run() { b=1; y=a; latch.countDown(); } }); one.start(); other.start(); latch.await(); String result="第"+i+"次(x"+x+","+y+")"; if(x==0&&y==0){ System.out.println(result); break; } } } }
想要实现有序性我们可以考虑volatile因为它有两个作用一个是保持可见一个是禁止重排,当然我们也可以通过synchronized和Lock来保证每个时刻是有一个线程执行同步代码,相当于让线程顺序执行同步代码,就可以保证其有序性。
这篇关于Java如何实现并发的原子性、可见性和有序性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-10百万架构师第十三课:源码分析:Spring 源码分析:Spring核心IOC容器及依赖注入原理|JavaGuide
- 2025-01-10便捷好用的电商API工具合集
- 2025-01-09必试!帮 J 人团队解决物流错发漏发的软件神器!
- 2025-01-09不容小觑!助力 J 人物流客服安抚情绪的软件!
- 2025-01-09为什么医疗团队协作离不开智能文档工具?
- 2025-01-09惊叹:J 人团队用啥软件让物流服务快又准?
- 2025-01-09如何利用数据分析工具优化项目资源分配?4种工具推荐
- 2025-01-09多学科协作难?这款文档工具可以帮你省心省力
- 2025-01-09团队中的技术项目经理TPM:工作内容与资源优化策略
- 2025-01-09JIT生产管理法:优化流程,提升竞争力的秘诀