【发布时间】:2015-11-15 01:31:44
【问题描述】:
这很尴尬,但我无法弄清楚这个简单的代码。
AtomicReferenceTest 启动多个线程,所有线程都引用同一个 id 生成器。
IdGenerator 没有线程安全性并维护一个由多个线程递增的变量,因此我完全希望线程打印出其他线程已经报告的重复值,但这不是我所看到的.
当我打印出值时,我看不到重复值,但线程似乎看到其他线程更新的值。
这怎么可能,我错过了什么?
public class AtomicReferenceTest {
public static void main(String args[]) throws InterruptedException {
AtomicReferenceTest.lockingIdGenerator();
}
public static void lockingIdGenerator() throws InterruptedException {
// Change the value in the first parameter to allow more threads to run simultaneously
IdGenerator idGenerator = new OneIdThreadGenerator();
ExecutorService tpe = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
tpe.execute(new Runnable() {
long id = 0;
@Override
public void run() {
final long threadId = Thread.currentThread().getId();
System.out.println("Value of id in " + threadId + " is = " + id);
while (id < 1000) {
id = idGenerator.nextId();
System.out.println(threadId + " : " + id);
}
System.out.println("Stopping thread : " + threadId);
}
});
}
tpe.shutdown();
tpe.awaitTermination(1, TimeUnit.DAYS);
}
}
OneIdThreadGenerator:
/**
* This class has no thread safety at all
*/
class OneIdThreadGenerator implements IdGenerator{
private long id = 0;
public long nextId() {
id = id + 1;
return id;
}
}
我的系统规格是:
型号名称:MacBook Pro
处理器名称:英特尔酷睿 i7
处理器速度:2.5 GHz
处理器数量:1
核心总数:4
L2 缓存(每个核心):256 KB
L3 缓存:6 MB
内存:16 GB
【问题讨论】:
-
有趣的问题,但只是为了确定;您能否添加您的环境的简短摘要(CPU 架构;执行单元的数量,即 CPU 内核和 SMT(如果适用);JRE 或 JDK 的供应商和版本)?
-
我自己运行了这段代码,实际上看到了很多重复...并且某些线程的 id 值高达 1009
-
JVM 调度程序可能很奇怪 :P 它有时可以决定表现得很好并提供线程安全的行为,但不要指望它......
-
@tixopi 您的评论具有误导性; JVM 调度程序的行为方式应该与 JMM 允许它在线程安全方面的行为方式相同。在这种情况下,OP 可能不会像她预期的那样看到错误,但 JMM 确实允许重复值。
-
@fge 抱歉,是的,我当然不是说 JVM 会一直这样。这只是一个轻松的评论,试图预测调度程序的行为可能是徒劳的:P
标签: java multithreading