volatile修饰全局变量,可以保证线程并发安全吗?


 

今天被人问到volatile能不能保证并发安全?

呵,这能难倒我?

上代码:(代码太长建议跳到页末)

//电脑太好,100线程起步~
public class ThreadTest { private static volatile int num = 0; public static void main(String[] args) throws InterruptedException { new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); new Thread(() -> { for (int i = 0; i < 100; i++) { num++; System.out.println(num); } }).start(); Thread.sleep(500); System.out.println(num); } }

期望最终值:
  100 * 100 = 10000

输出结果:
  ...
  ...
  9998
  9998
 

分析:

  100个线程对volatilei修饰的num++,会被编译成以下三步:
   1.获取i的值;2.执行i+1;3.将结果赋值给i。
  volatile只能保证可见性,并不能保证原子性。

结论:
  volatile只能保证这3步在编译后指令不会被重新排序,并不能保证线程并发的数据安全。建议搭配上synchronized或其他Lock锁使用。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM