0

我对线程很陌生。我写了一个代码,并期望我的输出始终为 20000。但事实并非如此。请在下面找到代码:

class Runner4 implements Runnable {

    static int count = 0;

    public synchronized void increase() {
        count++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            increase();
        }
    }
}

public class threading4 {

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runner4());
        t1.start();
        Thread t2 = new Thread(new Runner4());
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(Runner4.count);
    }
}

有什么解释吗?

谢谢!!

4

3 回答 3

1

您正在同步代码中的两个不同对象(对应于您创建的两个对象)。因此,没有对共享静态变量的保护,并且您会得到不可预测的结果。基本上,您的程序中没有进行有效的同步。您可以通过简单的修改来解决此问题。

改变:

public synchronized void increase(){
    count++;
}

至:

public void increase(){
    synchronized(Runner4.class) {
        count++;
    }
}

请注意,我并不是说这是完成这种同步的最佳方式 - 但重要的一点是,如果您正在修改类级别的变量,您也需要类级别的同步。

于 2013-02-10T02:36:24.590 回答
0

count如果不是,您的代码将起作用static

public synchronized void increase() {
    // method body
} 

相当于

public void increase() {
    synchronized(this) {
        // method body
    }
}

由于countis statict1t2都使用不同的锁访问它,从而导致不确定的行为。要么Runner4.increase在一个普通锁上同步(Runner4.class或者一个private static锁对象可以正常工作),要么count是非静态的。

于 2013-02-10T02:35:55.840 回答
0

你试图实现你想要的方式并不是最好的方式。更好的方法是定义一个名为 Counter 的类,如下所示:

public class Counter 
{
    int count;
    public Counter()
    {
        count = 0;
    }
    public synchronized void increase() {
        count++;
    }

    public int getCount()
    {
        return count;
    }

}

该类具有增加和获取计数器的方法。您现在需要做的是让两个调用 increase() 方法的线程共享一个 Counter 对象。所以你的线程类看起来像这样:

class Runner4 extends Thread {

    Counter count;
    public Runner4(Counter c)
    {
        count = c;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            count.increase();
        }

    }
}

请注意,该类接受一个 Counter 对象并调用 increase 方法。该类还扩展了 Thread 而不是实现 Runnable。真的没有太大区别,只是现在你的Runner4可以使用Thread类的方法了。

从您的 main 定义一个 Counter 对象和两个 Runner4 线程,然后将 Counter 对象传递给它们中的每一个:

public static void main(String[] args) {

        Counter count = new Counter();
        Thread t1 = new Runner4(count);
        t1.start();
        Thread t2 = new Runner4(count);
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(count.getCount());
    }
于 2013-02-10T02:42:44.367 回答