0
点赞
收藏
分享

微信扫一扫

单核多线程可见性问题

蒸熟的土豆 2022-10-22 阅读 227

背景 学习群上有个同学提出问题,如下截图 image.png image.png

这里可以看到分歧点,我认为JMM协议规定了工作内存,那么即使是单核,JAVA虚拟机也会保证线程本地内存变量的私有性,所以会存在不可见。但是别的同学认为服务器算法本身在单核情况下使用同一个缓存,所以应该是可见的。 实践出真知,所以我写了个demo,使用VM配置了个单核虚拟机去做实验。代码如下 com.czl.thread.TicketThreadTest

package com.czl.thread;


public class TicketThreadTest implements Runnable {


  private int tickets = 100;
  String str = new String("");


  @Override
  public void run() {
    while (true) {
//       synchronized(str) {
      if (tickets > 0) {
        try {
          // 让线程睡眠10毫秒再往下执行(人为放大线程不安全的现象)
          Thread.sleep(10);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }


        System.out.println(Thread.currentThread().getName() + " is saling ticket " + tickets--);
      } else {
        break;
      }
//       }
    }


  }


}

com.czl.thread.ThreadDemo1

package com.czl.thread;


/**
* 这个例子能看出高并发时,会出现票超卖的情况(出售大于库存)
*/
public class ThreadDemo1 {


   /**
    * @param args
    */
   public static void main(String[] args) {
//    new TestThread().run();
//    new TestThread2().start();
      TicketThreadTest t = new TicketThreadTest();
      new Thread(t).start();
      new Thread(t).start();
      new Thread(t).start();
      new Thread(t).start();
//    while (true) {
//       System.out.println(Thread.currentThread().getName() + "** is running!");
//    }


   }


}

运行结果如下图 image.png image.png

虽然最终还是超了100,存在线程安全问题,但是确实是可见的。从日志中不难看出,ticket-1都有被其它线程感知的,所以没有出现重复ticket号码的情况。那为什么超过了100呢?这应该是指令重排导致的。这个讨论给我扫了个盲点,挺有意义的,所以记录下

举报

相关推荐

0 条评论