并发编程中的三个问题
Posted lililixuefei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程中的三个问题相关的知识,希望对你有一定的参考价值。
可见性
package juc.synchronized_test; ? import java.util.concurrent.TimeUnit; ? /** * @author : 雪飞oubai * @date : 2020/4/9 11:07 * 目的:演示可见性问题 * 1、创建一个贡献变量 * 2、创建一条线程不断的读取共享变量 * 3、创建一条线程修改共享变量 */ public class Test01Visibility { // 多个线程都会访问的数据,我们称为线程的共享数据 private static boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(() -> { while(flag){ ? } }).start(); ? TimeUnit.SECONDS.sleep(1); ? new Thread(() -> { flag = false; System.out.println("时间到,线程2设置为false"); }).start(); } }
原子性
概念:原子性(Atomicity)在一次或多次操作中,要么所有的操作都执行并且不会受其它因素影响,要么所有的操作都不执行;
package juc.synchronized_test; ? import java.util.ArrayList; import java.util.List; ? /** * @author : 雪飞oubai * @date : 2020/4/9 11:27 * 目标:演示原子性问题 * 1、定义一个共享变量 number * 2、对number进行10000次 ++ 操作 * 3、使用 5 个线程来进行 */ public class Test02Atomicity { //1、定义一个共享变量 number private static int number = 0; ? public static void main(String[] args) throws InterruptedException { Runnable increment = () -> { for (int i = 0; i < 10000; i++) { number++; } }; List<Thread> list = new ArrayList<>(); ? for (int i = 0; i < 5; i++) { Thread t = new Thread(increment); t.start(); list.add(t); } for (Thread thread : list) { thread.join(); } System.out.println("number="+number); } }
其中,对于 number ++ 而言(number为静态变量),实际会产生如下的JVM字节码指令
由此可见 number++ 是由多条语句组成,以上多条指令在一个线程的情况下不会出现问题,但是再多线程情况下就可能会出现问题。比如一个线程在执行 13:iadd时,另一个线程又执行 9:getstatic,会导致两次number++,实际上只会加一次;
小结
并发编程会出现原子性问题,当一个线程对共享变量操作到一半时,另外的线程也有可能来操作共享变量,干扰了前一个线程的操作;
有序性
概念:有序性(Ordering)是指程序中代码的执行顺序,Java在编译时和运行时会对代码进行优化,会导致程序最终的执行顺序不一定就是我们编写代码时的顺序;
以上是关于并发编程中的三个问题的主要内容,如果未能解决你的问题,请参考以下文章
[Java 并发编程实战] 设计线程安全的类的三个方式(含代码)
JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段