2010-08-15 34 views
5

Tôi đang thử nghiệm Java Multi-Threading bằng cách sử dụng đồng bộ hóa trên phương pháp so sánh với biến Nguyên tử (gói java.util.concurrent.atomic).java đã đồng bộ hóa trên phương thức Không hoạt động?

Dưới đây là các lớp:

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

Kết quả từ chạy một trong hai nguyên tử hoặc đồng bộ không chỉ ra rằng số nguyên biến là thread-an toàn, ví dụ:

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 
------------------- 

Từ các kết quả, 2 dòng cuối cùng cho thấy 2 luồng đang truy cập cùng một giá trị của biến số nguyên của lớp truy cập. Có lẽ tôi đang thiếu điều gì đó ở đây?

Cảm ơn!

Trả lời

4

Bạn đang tăng giá trị trong một bước, sau đó nhận giá trị trong một bước khác. Trong khi mỗi bước riêng lẻ này được đảm bảo là nguyên tử bởi lớp AtomicInteger, thực tế là bạn thực hiện hai thao tác riêng biệt để lại giá trị mà bạn thấy trong bản in của mình theo lòng thương xót của thứ tự thực hiện của chuỗi.

Để có thể hiển thị chính xác giá trị được cập nhật bởi một chuỗi nhất định, bạn cần cập nhật và nhận giá trị kết quả trong một thao tác, phương pháp getIncrement() của bạn. Mã sẽ cung cấp cho bạn kết quả mong đợi sẽ trông như sau:

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

Những gì bạn bỏ lỡ là lớp AtomicCounter của bạn không hoạt động chính xác, và hành vi quan sát xảy ra becase các chủ đề chuyển giữa các cuộc gọi đến .increment().value():

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

counter.increment() của bạn và System.out.println không phải là một hành động nguyên tử .

Thread 1    Thread2 

increment 

         increment 

         System.out.println // print 10 

System.out.println 
// print 10 too 
Các vấn đề liên quan