从零学Java 多线程的三个特性

多线程的三个特性

多线程要保证并发线程正确执行,必须要保证三个特性。

1 原子性(互斥性):

  • 一个或多个操作不能被分割,要么全部执行,要么就都不执行。

2 可见性:

  • 多个线程访问同一个变量,一个线程修改了这个变量,别的线程能立即看到修改的值。
  • volatile关键字保证内存可见性。

3 有序性:

  • 程序执行的顺序按照代码的先后顺序执行。
  • 在单线程中处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行顺序和编写顺序一致,但最终结果是一致的。但是多线程可能会有问题。
  • volatile保证有序性(禁止指令重排序)。

三个特性的实现

synchronized可保证原子性和可见性。但不能保证有序性。

volatile可保证可见性和有序性。但不能保证原子性。

volatile 关键字配合 synchronized 或 Lock接口 实现了原子性、可见性、有序性。

eg:

volatile: 不稳定, 易挥发的 (解除子线程缓存)

public class TestVolatile {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        System.out.println("输入任意字符结束子线程");
        Scanner input = new Scanner(System.in);
        input.next();
        myThread.flag = true;
        System.out.println("flag: "+myThread.flag);
    }

    static class MyThread extends Thread {
        volatile boolean flag = false;

        @Override
        public void run() {
            System.out.println("子线程开始执行...");
            while (true) {
                if (flag) {
                    break;
                }
            }
            System.out.println("子线程结束了...");
        }
    }
}

内存分析:

从零学Java 多线程的三个特性_第1张图片

面试题

i++是原子操作吗? 不是原子操作。

(1)读取i的值 (2)执行加1操作(3)修改i的值

使用原子操作类解决。

TestAtomic:

public class TestAtomic {
    public static void main(String[] args) {
        Atomic atomic = new Atomic();
        ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            es.submit(()-> System.out.println(atomic.getNum()));
        }
        es.shutdown();
    }

    static class Atomic {
//        private int num = 0;
        private final AtomicInteger integer = new AtomicInteger();

        public int getNum() {
            return integer.getAndIncrement();
        }
    }
}

你可能感兴趣的:(从零学Java,java,面试,开发语言)