Java: 为什么我的同步输出还是那么随机

Java: Why is my synchronized output still so random

所以我第一次练习同步。我正在尝试实施 Oracle Java 并发教程中大体描述的实践概念。

想法是有一个特殊的 Counter 对象,具有递增、递减和显示值的方法。我的目标是通过两个不同的线程获取它 运行 以产生 运行dom 冲突,然后通过同步来解决这些冲突。到目前为止,我觉得第二部分不起作用,我无法弄清楚我做错了什么。

我在下面粘贴的代码很简单。有两个线程,有两个 运行nables。每个 运行 启用:

1) 包含对同一个 Counter 对象的引用 2) 运行s 循环五次 3)每次循环休眠1秒运行s 4) 打印计数器的当前值。

MyRunnable1 和 MyRunnable2 之间的唯一区别是第一个增加计数器,第二个减少计数器。

显然,当我 运行 它没有同步方法时,它产生了 运行dom 结果。但即使在我同步方法之后,结果显然仍然是 运行dom.

样本结果 1: 1个 0 1个 0 1个 0 -1 0 1个 0

样本结果 2: -1 0 1个 0 1个 0 1个 0 -1 0

我认为它应该是什么:它应该始终如一地运行 1 0 1 0 1 0 等等,直到所有循环都完成。如果我在那里错了,如果这是我对线程行为的思考方式,请指出。

下面是我的代码。所有 thoughts/advice 表示赞赏。这是我第一次尝试以任何方式使用同步,我想记下它,因为它是一个非常重要的概念。

public class CounterSync {

    public static void main(String[] args){
        Counter c = new Counter();

        Thread t1 = new Thread(new MyRunnable1(c));
        Thread t2 = new Thread(new MyRunnable2(c));
        t1.start();
        t2.start();
        System.out.println("Done");
    }

    public static class Counter{
        private int c = 0;

        public synchronized void increment(){
            c++;
        }

        public synchronized void decrement(){
            c--;
        }

        public synchronized int value(){
            return c;
        }
    }

    public static class MyRunnable1 implements Runnable{
        private Counter c;

        public MyRunnable1(Counter c){
            this.c = c;
        }

        @Override
        public void run(){

            try{
                for(int i = 0; i < 5; i++){
                    Thread.sleep(1000);
                    c.increment();
                    System.out.println(c.value());
                }
            }catch(InterruptedException ex){
                ex.printStackTrace();
            }
        }
    }


    public static class MyRunnable2 implements Runnable{
        private Counter c;

        public MyRunnable2(Counter c){
            this.c = c;
        }

        @Override
        public void run(){
            try{
                for(int i = 0; i < 5; i++){
                    Thread.sleep(1000);
                    c.decrement();
                    System.out.println(c.value());
                }
            }catch(InterruptedException ex){
                ex.printStackTrace();
            }
        }
    }


}

同步不代表有序。也许 'synchronization' 这个词具有误导性。在您的情况下,当一个人具有同步方法时,这意味着在给定的瞬间,最多一个线程可以 运行 一个 同步 方法在相关对象上。

您可以将 'synchronized' 读为 'one at a time'。

当您有多个线程时运行,每个线程的进度由系统决定。此外,Thread.sleep 保证在给定的时间间隔内至少 睡眠,但 是准确的。这两个事实结合起来会给你随机排序。