以下代码的运行在不同时间输出6,7,8。我不知道为什么。每个线程都有count变量,它是私有的。然后他们如何共享相同的变量?
public class ThreadSafety {
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
//wait for threads to finish processing
t1.join();
t2.join();
System.out.println("Processing count="+pt.getCount());
}
}
class ProcessingThread implements Runnable{
private int count = 0;
@Override
public void run() {
for(int i=1; i< 5; i++){
processSomething(i);
count++;
}
}
public int getCount() {
return this.count;
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
由于
答案 0 :(得分:5)
你有两个线程,但只有一个对象。当然,这些线程将共享单个对象的所有变量。如果您创建了2个ProcessingThread
个对象并为两个线程提供了自己的实例,则不会发生这种情况。
答案 1 :(得分:0)
启动时新的线程只有自己的执行上下文。它不会创建对象的副本,也不会维护自己的内存空间。它将代替共享堆内存。
在您的情况下,您已在堆上创建了一个对象,并将相同的对象引用传递给两个线程。当两个线程同时执行时,它们共享同一个对象,这会在访问count变量和执行count ++时出现竞争条件。这导致输出不一致。
如果您正在共享相同的对象并且喜欢将结果视为8,请将count ++放在synchronized块中,如下所示
public void run() {
for(int i=1; i< 5; i++){
processSomething(i);
synchronized(this) {
count++;
}
}
}
如果您正在共享您不想共享特定对象变量的对象,请将其声明为本地线程。