Java:为什么我的同步输出仍然是如此随机

时间:2015-05-17 02:27:51

标签: java synchronization

所以我第一次练习同步。我正在尝试实现一般在Oracle Java Concurrency教程中描述的实践概念。

我们的想法是拥有一个特殊的Counter对象,其中包含递增,递减和显示值的方法。我的目标是让它由两个不同的线程运行以生成随机冲突,然后通过同步解决这些冲突。到目前为止,我觉得第二部分不起作用,我无法弄清楚我做错了什么。

我在下面粘贴的代码很简单。有两个线程,有两个runnables。每个runnable:

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

MyRunnable1& amp; MyRunnable2是第一个递增计数器,第二个递减计数器。

显然,当我在没有同步方法的情况下运行它时会产生随机结果。但即使在我同步这些方法后,结果仍显然是随机的。

样本结果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等等,直到完成所有循环。如果我错在那里,如果这是我考虑线程行为的方式,请指出。

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

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();
            }
        }
    }


}

1 个答案:

答案 0 :(得分:1)

同步并不意味着订购。也许“同步”这个词有误导性。在您的情况下,当一个人有同步方法时,这意味着在给定的时刻,一个线程可以在相关对象上运行 synchronized 方法。

您可以将“同步”视为“一次一个”。

每当运行多个线程时,每个线程将进行多少进程由系统决定。此外,Thread.sleep保证在给定的时间间隔内至少,但精确。两个事实相结合将给你随机排序。