2015-11-06 34 views
2

我對多線程編程的經驗不多。我有多線程寫入文件。我想知道有什麼區別:具有同步功能的單例類與靜態同步函數有什麼區別

實施1:一個具有靜態同步功能的類。每個線程調用FileUtil.writeToFile()

public class FileUtil { 

    public static synchronized void writeToFile(String filename) { 
     // write to file.... 
    } 
} 

實現2:一個單獨的類。每個線程調用Fileutil.getInstance()。將writeToFile()

public class FileUtil { 
    private static final FileUtil fileManager = new FileUtil(); 
    private FileUtil() { 
    } 

    public synchronized void writeToFile(String filename) { 
     // write to file.... 
    } 

    public static FileUtil getInstance() { 
     return fileManager; 
    } 
} 
+1

我不參與投票。我會鏈接到[this](http://stackoverflow.com/questions/437620/java-synchronized-static-methods-lock-on-object-or-class),它解釋了類與實例方法中的同步差異。之後唯一的區別就是你正在調用一個額外的方法,第二種情況是'getInstance'。 –

+0

@SotiriosDelimanolis所以我想也許實現1和2都可以,並且線程安全。實施1是一個更清潔和更簡單的方法? –

+2

我認爲這減少了是否使用靜態方法或單例模式的類的問題。同步的差異只是顯示器。 – RealSkeptic

回答

3

沒有實用差異。

實際上,無論哪種方式,您都有一個唯一的鎖對象,所有呼叫者都必須獲取才能進入該方法。

唯一的區別是鎖對象的身份:在單例情況下,鎖對象是單例。在靜態方法的情況下,它是Class對象。

0

總之,沒有真正的區別。

這裏要注意的一點是,在synchronization number 1(靜態同步方法),所有的線程將在獲取Class對象的鎖(表示FileUtil類),只有一個線程將獲得在鎖定時間競爭,執行該方法。

在第二種情況下,所有線程將再次競爭獲取與「this」對象關聯的監視器(並且只有一個線程將一次獲取並執行)。注意我們正在討論一個單例,所以在這個地址空間中只有一個實例(如果這個類同時通過多個類加載器加載,但我們離題了,那麼可能會有多個實例)。

在任何一種情況下,所有線程都會競爭鎖定一個對象:類描述對象或「this」對象和,因此在運行程序時沒有實際區別。在第二種情況下創建FileUtil的一個實例並將其放在堆上但是這是不重要的,因此存在輕微的堆差異。

3

在你的問題的問題可以分爲:

對於顯示器的選擇,還有第三個選項:

使用監控對象不是給調用者訪問。這樣做的好處是,如果班級的用戶或單身人士決定在他自己的程序中使用該班級或單身人士作爲監視器,則不會導致阻止對writeToFile()的所有呼叫。

也就是說,假設有人做到這一點:

FileUtil obj = FileUtil.getInstance(); 
synchronized (obj) { 
    // Some long operation 
} 

因爲writeToFile()方法對同一實例同步,沒有其他的線程將能夠使用writeToFile()直到「長作業」等做同步塊離開了。

現在,相反,如果你這樣做:

public class FileUtil { 
    private static final FileUtil fileManager = new FileUtil(); 
    private static final Object lock = new Object(); // To be used for synchronizing 

    private FileUtil() { 
    } 

    public void writeToFile(String filename) { 
     synchronized (lock) { 
      // write to file.... 
     } 
    } 

    public static FileUtil getInstance() { 
     return fileManager; 
    } 
} 

那麼,即使你的類的用戶決定使用它作爲一個鎖(無論是班上的班長或實例監視器),它不會干擾writeToFile()的功能。

0

兩者在提供相同的結果上是等同的。

但我更喜歡第二個實施辛格爾頓類+ RealSkeptic的建議有靜態最終鎖定對象

優勢與辛格爾頓:在未來,你可以用一定規模(FileUtil的例如爲:5級的對象)改變辛格爾頓到ObjectPool的FileUtil。與第一個實現中的靜態同步方法相比,您可以通過使用靜態對象鎖的FileUtil池進行更多控制。

相關問題