2011-04-19 73 views
18

根據許多人的說法,除非您運行1.5或更高版本並使用volatile關鍵字,否則Java的某些常見的Double-Checked Locking成語已被破壞。Android中的雙重鎖定鎖定

阿破雙重檢查鎖定樣本:

// Broken multithreaded version 
// "Double-Checked Locking" idiom 
class Foo { 
    private Helper helper = null; 
    public Helper getHelper() { 
    if (helper == null) 
     synchronized(this) { 
     if (helper == null) 
      helper = new Helper(); 
     }  
    return helper; 
    } 
    // other functions and members... 
    } 

樣本來源於此文章,這也提供了關於如何解決它的詳細信息:以上 http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Pugh的分析是Java虛擬機。我使用Android並經常使用採用雙重檢查鎖定的庫。達爾維克虛擬機的內存模型是否支持這種習慣用法?

+0

你可以猜到我在看什麼;) – Snicolas 2014-02-10 21:11:23

回答

10

對此question的回答意味着內存模型應該是相同的,並且新的雙重檢查鎖定方式將起作用。

+1

是的。通過添加「volatile」關鍵字,這將適用於單處理器(所有版本的Android)和SMP(3.0「蜂窩」及更高版本)。 – fadden 2011-04-19 22:31:14

+0

否則,在蜂窩之前,是否可以使用非易失性字段進行雙重鎖定檢查? @Fadden順便說一句,在dalvik java.lang.Class類中是否有任何反射調用緩存?通過緩存,我的意思是有一些像在Java VM上的字節碼生成:stackoverflow.com/a/414823/693752 – Snicolas 2014-02-10 21:21:14

+1

您需要使用某種類型的同步操作('volatile','synchronized'等),如Pugh's所示現場。問題中的破碎的例子已經被打破了,不應該被使用。在Dalvik中實現反射的過程已經發生了一些變化,所以您必須查看給定發佈的代碼才能確切知道它的功能。我相信有一些緩存,但據我所知,字節碼生成不是所使用的技術之一。 – fadden 2014-02-10 22:22:11

0

我發現關於這個問題一個很好的文章: http://www.javamex.com/tutorials/double_checked_locking_fixing.shtml

它明確指出3種方式來解決DCL。在你的問題中,Helper字段應該被聲明爲volatile,否則它不起作用。

在你的情況下,如果使用RoboGucie,我想我會贊成文中提到的類加載器方法。這對我來說更加清楚,而且效率更高。