2013-04-14 40 views
28

Tôi có siêu lớp Point và phương thức synchronizeddraw(). Các lớp con của số Point có kế thừa synchronized nếu tôi ghi đè phương thức draw() vào chúng hay tôi phải luôn viết nó?Được đồng bộ kế thừa trong Java?

+0

thể trùng lặp của [Trọng một cách đồng bộ phương pháp] (http://stackoverflow.com/questions/10173345/overriding-a-synchronized-method) – Raedwald

Trả lời

28

Không, bạn sẽ luôn phải viết synchronized. Nếu bạn gọi phương thức đồng bộ của lớp siêu này tất nhiên sẽ là một cuộc gọi được đồng bộ hóa. synchronized không phải là một phần của chữ ký phương thức.

Xem http://gee.cs.oswego.edu/dl/cpj/mechanics.html để biết mô tả chi tiết từ Doug Lea, Java threading boss (hoặc hơn).

+2

Có thể làm rõ một chi tiết: cho dù cuộc gọi phương thức đã cho có được đồng bộ hay không phụ thuộc vào loại động của đối tượng mà nó được gọi, không phải kiểu tĩnh. Tức là, nếu 'foo()' là 'đồng bộ' trong' Derived' nhưng không phải trong 'Base', và bạn gán một' Derived' vào biến 'Base' và gọi' foo() 'trên đó, cuộc gọi đó sẽ được đồng bộ hóa. Điểm này là ẩn trong 8.4.3.6 của spec ngôn ngữ (mà nói một phương thức 'sync' tương đương với câu lệnh' synchronized' trong phương thức đó), nhưng tôi không thể tìm thấy nó được viết ra ở bất cứ nơi nào khác. Runnable demo [ở đây] (http://runnable.com/U4zBThIj5WNju2g2/). – mrec

4

phương pháp Overriden của bạn sẽ không còn được đồng bộ nếu bạn Ghi đè lên và xóa synchronized. Đã tìm thấy nó herehere

+1

Không có trích dẫn nào của bạn là một tham chiếu quy phạm. – EJP

10

Bạn có thể kiểm tra xem nó cho mình bằng cách viết này:

public class Shape { 

    protected int sum = 0; 

    public synchronized void add(int x) { 
     sum += x; 
    } 
} 


public class Point extends Shape{ 

    public void add(int x) { 
     sum += x; 
    } 

    public int getSum() { 
     return sum; 
    } 
} 

Và kiểm tra lớp

public class TestShapes { 

    public final static int ITERATIONS = 100000; 

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

     final Point p = new Point(); 

     Thread t1 = new Thread(){ 
      @Override 
      public void run() { 

       for(int i=0; i< ITERATIONS; i++){ 
        p.add(1); 
       } 
      } 
     }; 

     Thread t2 = new Thread(){ 
      @Override 
      public void run() { 

       for(int i=0; i< ITERATIONS; i++){ 
        p.add(1); 
       } 
      } 
     }; 

     t1.start(); 
     t2.start(); 

     t1.join(); 
     t2.join(); 


     System.out.println(p.getSum()); // should equal 200000 

    } 
} 

Trên máy tính của tôi nó là 137.099 thay vì 200000.

+2

Cách dễ dàng hơn để kiểm tra sẽ là kiểm tra trên ['Thread.holdsLock (this);'] (http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#holdsLock% 28java.lang.Object% 29) theo phương pháp ghi đè –

+4

Không trả lời câu hỏi. Mã thử nghiệm chỉ có thể làm lộ một lỗi hoặc một thời gian bất thường do một cái gì đó khác ngoài đồng bộ hóa. Câu trả lời là được tìm thấy trong đặc tả ngôn ngữ. – EJP

+0

@EJP Lúc đầu, tôi nghĩ bạn đã sai. Sau đó, tôi nhận ra bạn thực sự đúng, nhưng khá bi quan ... – Timo