背景 学习群上有个同学提出问题,如下截图
这里可以看到分歧点,我认为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!");
// }
}
}
运行结果如下图
虽然最终还是超了100,存在线程安全问题,但是确实是可见的。从日志中不难看出,ticket-1都有被其它线程感知的,所以没有出现重复ticket号码的情况。那为什么超过了100呢?这应该是指令重排导致的。这个讨论给我扫了个盲点,挺有意义的,所以记录下
标签:单核,Thread,可见,start,thread,线程,new,多线程,public From: https://blog.51cto.com/u_15565709/5785828