多线程 - 为什么私有成员变量共享?

时间:2014-05-25 17:54:00

标签: java multithreading

以下代码的运行在不同时间输出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();
        }
    }

}

由于

2 个答案:

答案 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++;
        }
    }
}

如果您正在共享您不想共享特定对象变量的对象,请将其声明为本地线程。