volatile可见性代码验证

volatile可见性代码验证

大厂面试题:

1、请你谈谈对volatile的理解?

2、CAS你知道吗?

3、原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗?

4、我们都知道ArrayList是线程不安全的,请编码写一个不安全的案例并给出解决方案?

5、公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁。

6、CountDownLatch、CyclicBarrier、Semaphore使用过吗?

7、阻塞队列知道吗?

8、线程池用过吗?ThreadPoolExecutor谈谈你的理解?

9、线程池用过吗?生产上你是如何设置合理参数?

10、死锁编码及定位分析?

 

volatile可见性代码验证                 

Demo One:定义的变量没有被volatile修饰是没有可见性的

public class VolatileVisibleDemo {

    private int num = 0;

 

    public void addNum() {

        num = num + 60;

    }

 

    public static void main(String[] args) {

        VolatileVisibleDemo volatileVisibleDemo = new VolatileVisibleDemo();

        // t1线程对num就行更改操作

        new Thread(() -> {

            System.out.println(Thread.currentThread().getName() + "\t come in");

            try {

                // 模拟num更改操作耗时3m,并保证其他线程读取了num变量

                Thread.sleep(3000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            volatileVisibleDemo.addNum();

            System.out.println(Thread.currentThread().getName() + "\t" + "num值已经被更改为:" + volatileVisibleDemo.num);

        }, "t1").start();

 

        while (volatileVisibleDemo.num == 0) {

            // main线程一直等待,直到num不等于0

        }

        System.out.println(Thread.currentThread().getName() + "\t mission is over");

    }

}          

程序会一直卡在while循环那里,因为线程之间不可见,main线程永远拿不到子线程t1更改后的值。

volatile可见性代码验证

Demo Two:定义的变量被volatile修饰是可见的

public class VolatileVisibleTwoDemo {

       // 被volatile修饰的变量,线程间是可见的

    private volatile int num = 0;

 

    public void addNum() {

        num = num + 60;

    }

 

    public static void main(String[] args) {

        VolatileVisibleTwoDemo volatileVisibleDemo = new VolatileVisibleTwoDemo();

        // t1线程对num就行更改操作

        new Thread(() -> {

            System.out.println(Thread.currentThread().getName() + "\t come in");

            try {

                // 模拟num更改操作耗时3m,并保证其他线程读取了num变量

                Thread.sleep(3000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

                     // 当t1线程更改num之后,t1线程会把更新后的num值写回主内存空间,并通知main线程重新去主内存空间获取最新的副本变量。

            volatileVisibleDemo.addNum();

            System.out.println(Thread.currentThread().getName() + "\t" + "num值已经被更改为:" + volatileVisibleDemo.num);

        }, "t1").start();

 

        while (volatileVisibleDemo.num == 0) {

            // main线程一直等待,直到num不等于0

        }

        System.out.println(Thread.currentThread().getName() + "\t mission is over");

    }

}                     

 

程序执行结果如下:

volatile可见性代码验证

 

如果此时你已经把volatile可见性原理分析很清楚,接下来面试官可能会问你:

volatile为什么不保证原子性?

请你使用代码验证下volatile不保证原子性?

有什么办法让volatile保证原子性?

参考答案请看下一小节:volatile不保证原子性