volatile与内存可见性

ゞ 浴缸里的玫瑰 2022-07-12 06:26 360阅读 0赞
  1. 在多线程环境下,对共享变量的操作,往往会遇到内存可见性问题。先看下面一段代码:
  2. public class TestVoltatile {
  3. public static void main(String[] args) {
  4. ThreadDemo td = new ThreadDemo();
  5. new Thread(td).start();
  6. while (true) {
  7. if (td.isFlag()) {
  8. System.out.println("------------------");
  9. break;
  10. }
  11. }
  12. }
  13. }
  14. class ThreadDemo implements Runnable {
  15. private boolean flag = false;
  16. public void run() {
  17. try {
  18. Thread.sleep(200);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. flag = true;
  23. System.out.println("flag=" + isFlag());
  24. }
  25. public boolean isFlag() {
  26. return flag;
  27. }
  28. public void setFlag(boolean flag) {
  29. this.flag = flag;
  30. }
  31. }
  32. 这段你代码中,有两个线程,一个是main线程,一个是自己创建的线程(以下称为Thread-0)。其中Thread-0线程的run方法中去修改flag的值,main线程死循环判断flag的值如果为true则退出循环。运行上面的代码,发现 Thread-0线程输出flag=true,但是程序却没有停止。
  33. 这个问题涉及到了flag变量的内存可见性问题。每个线程在执行中都有一块缓存区,flag变量是类的属性,在堆中分配空间。当Thread-0线程要对flag的值进行修改的时候,会先到堆内存中读取flag的值到自己的线程缓存中,然后修改其值。修改之后,还没来得及将其写入到堆内存中,main线程在循环中判断isFlag()的时候就把堆中的flag值读到了自己的缓存中,此时为false。由于while(true)循环在jvm底层有做了优化,所以每次循环判断的falg值是main线程缓存中的,一直都是false。所以导致了flag值被修改后,main线程还是没有停止下来,一直在死循环。这就是内存可见性问题。
  34. 解决这个问题我们可以使用同步,使用synchronized同步代码块将if包围起来,这样每次都能刷新缓存,取到最新的flag值。但是使用锁会导致性能的下降,多线程就会出现等锁的情况。
  35. 还有一个解决方式就是使用volatile关键字修饰flag变量。被volatile修饰的变量,在每次使用时,都会到内存中去取最新的值,这就解决了多线程间内存可见性的问题,当多个线程进行操作共享数据时,可以保证内存中的数据可见。volatile不同于synchronizedvolatile不具备”互斥性”,即多个线程可以同时访问,不需要抢锁。并且,volatile不能保证变量的"原子性"
  36. 解决方式一:
  37. public static void main(String[] args) {
  38. ThreadDemo td = new ThreadDemo();
  39. new Thread(td).start();
  40. while (true) {
  41. synchronized (td) {
  42. if (td.isFlag()) {
  43. System.out.println("------------------");
  44. break;
  45. }
  46. }
  47. }
  48. }
  49. 解决方式二:
  50. private volatile boolean flag = false;

内存可见性问题还可参考一下博客:

http://blog.csdn.net/beiyetengqing/article/details/49583381

http://www.cnblogs.com/frydsh/p/5720658.html

http://www.cnblogs.com/longshiyVip/p/5211476.html

发表评论

表情:
评论列表 (有 0 条评论,360人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Volatile可见

    Volatile 使变量在多个线程可见 每一个线程都会有一块工作内存区 其中,存放着所有线程共享的主内存中的变量值的拷贝 当线程执行时 在自己的工作区内存中