【发布时间】:2016-10-09 23:22:34
【问题描述】:
我正在学习 Java,来自 python 背景,并试图理解线程干扰,从本页中的代码和解释开始:http://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html
为了重现干扰,我有另一个类启动三个线程,每个线程随机调用递增或递减 10 次。
我预计,在 3 个线程和 30 个增量或减量的情况下,有些会重叠,因此最终的 Counter 值将不等于 (# increments) - (# decrements)。
但每次我运行代码并分析结果输出时,我发现最终值等于 (# increments) - (# decrements)。虽然有可能在运行 5 次后不知何故没有受到任何干扰,但更可能是我误解了干扰效果或无意中实现了避免干扰的代码。
这是我的代码:
// file: CounterThreads.java
public class CounterThreads {
private static class CounterThread implements Runnable {
private Counter c;
CounterThread(Counter c)
{
this.c = c;
}
public void run()
{
String threadName = Thread.currentThread().getName();
for (int i=0; i<10; i++) {
try {
if (((int)(Math.random() * 10) % 2) == 0) {
System.out.format("%s - Decrementing...\n", threadName);
c.decrement();
} else {
System.out.format("%s - Incrementing...\n", threadName);
c.increment();
}
System.out.format("%s - The internal counter is at %s\n", threadName, c.value());
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.format("Thread %s interrupted\n", threadName);
}
}
}
}
public static void main(String[] args)
{
Counter c = new Counter();
for (int i=0; i<3; i++) {
Thread t = new Thread(new CounterThread(c));
System.out.format("Starting Thread: %s\n", t.getName());
t.start();
}
}
}
Counter.java 文件包含从上面的 oracle 文档中复制的代码,为方便起见,在此复制
// file: Counter.java
public class Counter {
private int c = 0;
void increment ()
{
c++;
}
void decrement()
{
c--;
}
int value()
{
return c;
}
}
【问题讨论】:
-
建议:从运行一个线程开始,看看你是否获得了除
0以外的任何东西——如果没有,那么你的检测方法有问题。 -
要查看干扰,您必须创建实际的并发执行。您编写的代码在 纳秒 内执行递增或递减,然后休眠一整秒。两个线程以完全相同的纳秒分派的机会微乎其微。您需要编写在紧密循环中同时在多个线程中执行增量和减量数百万次的代码,并在每次迭代后检查意外值。 IE。获取值的线程本地副本,增加/减少副本,增加/减少值,比较。
-
只要加法和减法是原子操作,
Counter的值将始终等于(# increments) - (# decrements),所以这并不奇怪 -
但是,如果您在某个特定线程(例如 thread1)中更新计数器,然后尝试输出它的值,它可能会在输出操作之前被另一个线程更新,因此输出将在内部不一致thread1的范围
-
同上他们所说的(上图):摆脱
sleep()电话。此外,不是让每个线程执行十个操作,而是让每个线程执行十 百万。
标签: java multithreading java-threads