2013-04-10 38 views
8

Từ khóa đồng bộ hóa có cần phải được áp dụng cho từng phương pháp của lớp thực hiện mẫu đơn như thế này không?Java đồng bộ hóa trong mẫu đơn

public class Singleton { 

    private Singleton(){} 

    public synchronized static Singleton getInstance() 
    { 
     if(instance == null) 
      instance = new Singleton(); 

     return instance; 
    } 

    public void DoA(){ 
    } 
} 

Kể từ Singletons không tiếp xúc với một nhà xây dựng cộng đồng và các phương pháp getInstance() được đồng bộ, người ta không cần phải đồng bộ phương pháp DoA và bất kỳ phương pháp nào khác hiển thị bởi lớp Singleton.

Đây có phải là lý do chính xác không?

+2

En chung sychronization phụ thuộc nếu bạn truy cập dữ liệu được chia sẻ trong phương pháp này. – PeterMmm

+0

[Điều này sẽ trả lời câu hỏi của bạn] (http://stackoverflow.com/questions/777849/proper-usage-of-synchronized-singleton) – user1406177

+1

Tôi không nghĩ vậy, Nếu getInstance được đồng bộ hóa. điều đó không có nghĩa là DoA được đồng bộ hóa. quá. –

Trả lời

16

Giống như bất kỳ lớp nào khác. Có thể hoặc không cần đồng bộ hóa thêm.

Hãy xem xét ví dụ sau:

public class Singleton { 

    private Singleton() {} 

    public synchronized static Singleton getInstance() { ... } 

    private int counter = 0; 

    public void addToCounter(int val) { 
    counter += val; 
    } 
} 

Nếu lớp được sử dụng từ nhiều chủ đề, addToCounter() có một điều kiện chủng tộc. Một cách để khắc phục điều đó là bằng cách làm cho addToCounter() đồng bộ:

public synchronized void addToCounter(int val) { 
    count += val; 
    } 

Có nhiều cách khác để sửa chữa tình trạng chủng tộc, ví dụ bằng cách sử dụng AtomicInteger:

private final AtomicInteger counter = new AtomicInteger(0); 

    public void addToCounter(int val) { 
    counter.addAndGet(val); 
    } 

Ở đây, chúng tôi đã khắc phục các tình trạng chủng tộc mà không cần sử dụng synchronized.

+0

Làm thế nào tôi có thể giải quyết lỗi PMD "Sử dụng mức khối thay vì đồng bộ hóa mức phương thức" trên getInstance? – rodi

+0

cảm ơn cho mẹo trên 'AtomicInteger'. – asgs

9

Vâng, mục đích của lớp Singleton là có tối đa một trường hợp của nó và tất cả các Chủ đề có thể truy cập cùng một đối tượng đó.

Nếu bạn không đồng bộ hóa các phương pháp getInstance sau đây có thể xảy ra

thread1 vào getInstance()

thread2 vào getInstance()

thread1 đánh giá instance == null để true

thread2 đánh giá instance == null để true

thread1 gán instance và trả

thread2 tái gán instance = new Singleton() và lợi nhuận.

Bây giờ các chủ đề cả hai đều có một thể hiện khác biệt của lớp Singleton đó là những gì nên đã được ngăn chặn bởi mô hình này.

Đồng bộ hóa ngăn cản cả hai Chủ đề có thể truy cập cùng một khối mã cùng một lúc. Vì vậy, việc đồng bộ hóa là cần thiết trong một môi trường đa luồng khi bạn khởi tạo các lớp singleton.

Bây giờ giả sử rằng nhiều luồng sẽ cố gắng truy cập các phương thức Singletons tại cùng một thời gian đồng bộ hóa có thể cần thiết đối với các phương thức đó. Đặc biệt nếu họ thay đổi dữ liệu thay vì chỉ đọc nó thì điều này là đúng.

+0

Tôi nghĩ câu hỏi đề cập đến các phương thức công khai của cá thể Singleton, chứ không phải là 'getInstance' tĩnh. – afsantos

+0

Vâng, tôi nên kiên nhẫn hơn và đọc câu hỏi trước khi trả lời. Tôi sẽ mở rộng câu trả lời ... – DeltaLima

1

Các chính xác (tốt nhất trên thực tế) cách để sử dụng Singleton

private static singleton getInstance() { 
    if (minstance == null) { 
     synchronized (singleton.class) { 
      if (minstance == null) { 
       minstance = new singleton(); 
      } 
     } 
    } 
    return minstance; 
} 
+0

nếu 'minstance' xảy ra là null, thì việc đồng bộ hóa khối với cá thể đó sẽ dẫn đến' NullPointerException'. – asgs

+0

Vâng. Trên thực tế tôi đã viết mã trước trong một vội vàng. ;) – gaurav414u

+0

đó là một yếu tố xấu - đó là mô hình khóa được kiểm tra kép - và sẽ không hoạt động sau khi tất cả - giải thích tại đây http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html –

1

khởi lười biếng và sợi giải pháp an toàn:

public class Singleton { 

    public static class SingletonHolder { 
     public static final Singleton HOLDER_INSTANCE = new Singleton(); 
    } 

    public static Singleton getInstance() { 
     return SingletonHolder.HOLDER_INSTANCE; 
    } 
} 
Các vấn đề liên quan