3

我有一个简单的代码片段,并尝试对其进行一些试验,但在下一个代码中,我不清楚输出数据的顺序:

public class Main {

    static int n = 100;

    public static synchronized int decreaseValue(){
        return --n;
    }

    public static void main(String[] args) throws InterruptedException, IOException {


        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread1: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread1");
        t1.start(); 

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread2: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread2");
        t2.start();


        while(true){
            try {
                System.out.println("Main Thread: "+ decreaseValue());
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

无法理解,为什么我会按下一个顺序获得这样的值:

线程 1:89 线程 2:90 主线程:88

请注意 N 值而不是调用线程的顺序:

Thread1: 99
Thread2: 98
Main Thread: 97
Main Thread: 95
Thread2: 94
Thread1: 96
Main Thread: 92
4

3 回答 3

3

您必须在某处阅读过synchronized必须用于确保正确排序的内容或类似内容。“排序”这个词与您所想到的概念不同:它意味着同步块的执行总会有一些确定的顺序。顺序是事先不知道的,但每次都会在那里。如果没有同步,您甚至不会得到保证:一个线程可以感知一个顺序,另一个线程可以感知不同的顺序,或者根本不感知其他线程的任何操作。

关于您的编辑:

如果您担心打印输出乱序,这是因为您的println语句在外部,synchronized因此可以独立于对decreaseValue.

于 2012-10-28T12:47:41.163 回答
2

线程并行运行。你无法预测他们的执行顺序。您可以设置线程优先级,确定其执行顺序的优先级。

于 2012-10-28T12:41:49.853 回答
1

线程同时运行,并且没有任何东西强加他们应该调用你的decreaseValue()函数的顺序。您会期望它们是有序的,因为您正在执行相同数量的睡眠 :),但是一旦线程从睡眠中启动/恢复,CPU 就会将该线程放入运行队列中(创建执行顺序,这是同步将保证的顺序),因此您的打印顺序取决于 CPU 将如何将线程放入运行队列中。

如果您质疑打印顺序,控制台上的打印也会同步(但与您的 reductionValue 不在同一块中)。相同的逻辑适用于打印作为减少值的逻辑。

如果您想以与值递减相同的顺序查看打印,您可以在decreaseValue()函数中移动打印。但这不会影响值递减的顺序。

于 2012-10-28T12:37:19.937 回答