java synchronized方法不工作?

时间:2010-08-15 19:50:02

标签: java multithreading concurrency atomic synchronized

我正在尝试使用方法上的同步与原子变量(java.util.concurrent.atomic包)进行Java多线程。

以下是课程:

// Interface ICounter.java
        public interface ICounter {
            public void increment();
            public void decrement();
            public int value();
        }

// Class Counter.java
    public class Counter implements ICounter {
        private int c = 0;

        @Override
        public void increment() {
            c++;
        }

        @Override
        public void decrement() {
            c--;
        }

        @Override
        public int value() {
            return c;
        }
    }

// Class AtomicCounter.java
    import java.util.concurrent.atomic.AtomicInteger;

    public class AtomicCounter implements ICounter {
        private AtomicInteger c = new AtomicInteger(0);

        @Override
        public void increment() {
            c.incrementAndGet();
        }

        @Override
        public void decrement() {
            c.decrementAndGet();
        }

        @Override
        public int value() {
            return c.get();
        }

        public long getIncrement() {
            return c.incrementAndGet();
        }
    }

// Class MainProg.java
    public class MainProg {
        public static void main(String args[]) {
            ICounter counter = new AtomicCounter();
                    //ICounter counter = new SynchronizedCounter();
            Thread thread1 = new Thread(new CountRunner(counter));
            Thread thread2 = new Thread(new CountRunner(counter));

            thread1.start();
            thread2.start();
        }
    }

    class CountRunner implements Runnable {
        private ICounter counter;
        public CountRunner(ICounter counter) {
            this.counter = counter;
        }

        public void run() {
            while (true) {
                counter.increment();
                System.out.println(Thread.currentThread().getName() + " count=" + counter.value());
                System.out.println("-------------------");
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

运行Atomic或Synchronized的结果不显示变量integer是线程安全的,例如:

Thread-0 count=1
-------------------
Thread-1 count=2
-------------------
Thread-0 count=3
-------------------
Thread-1 count=4
-------------------
Thread-0 count=5
-------------------
Thread-1 count=6
-------------------
Thread-0 count=7
-------------------
Thread-1 count=8
-------------------
Thread-0 count=10
-------------------
Thread-1 count=10
-------------------

从结果中,最后两行显示2个线程正在访问计数器类的整数变量的相同值。 也许我在这里错过了什么?

谢谢!

3 个答案:

答案 0 :(得分:4)

因为您的counter.increment()System.out.println不是一个原子动作。

Thread 1               Thread2

increment

                       increment

                       System.out.println  // print 10

System.out.println  
// print 10 too

答案 1 :(得分:4)

您只需一步递增值,然后在另一步中获取值。虽然这些单独的步骤中的每一个都被基础AtomicInteger类保证为原子,但是您进行两次单独操作的事实会使您在print语句中看到的值受到线程执行顺序的影响。

为了能够准确显示给定线程更新的值,您需要在getIncrement()方法执行的单个操作中更新并获取结果值。能给你预期结果的代码如下所示:

int changedValue = counter.getIncrement();
System.out.println(Thread.currentThread().getName() + " count=" + changedValue);

答案 2 :(得分:2)

您错过的是您的AtomicCounter类确实正常工作,并且由于线程在调用.increment().value()之间切换而发生了观察到的行为:

-------------------
Thread-0 increment -> value = 9
-------------------
Thread-1 increment -> value = 10
-------------------
Thread-0 print value <- 10
-------------------
Thread-1 print value <- 10
-------------------