2016-11-22 11 views
2

私はこのアンドロイドの実装を理解しようとしていますが、静的フィールドlockStaticが揮発性である理由を理解できません。なぜなら、その使用はgetLockメソッドだけであり、同期ブロックなので、並行性またはオブジェクト出版の問題。なぜAndroid用のlockStaticは揮発性ですか?

abstract public class WakefulIntentService extends IntentService { 
    abstract protected void doWakefulWork(Intent intent); 
    static final String NAME= 
     "com.commonsware.cwac.wakeful.WakefulIntentService"; 
    static final String LAST_ALARM="lastAlarm"; 

    private static volatile PowerManager.WakeLock lockStatic=null; 

    synchronized private static PowerManager.WakeLock getLock(Context context) { 
     if (lockStatic == null) { 
      PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 

      lockStatic=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME); 
      lockStatic.setReferenceCounted(true); 
     } 

     return(lockStatic); 
    } 

私はlockStaticはそれで他の方法でのアクセスが、そのプライベートと唯一の方法のウィッヒお得な情報がGETLOCK方法で許可された場合には揮発性のためにのみ必要があるだろう見る方法。これは単なる主張ですか、それとも背後にある他の理由がありますか?

この問題を解決する助けを前もってありがとうございます。サンプルコードで

WeakfullIntentService

+3

私は、ダブルチェックロック実装をサポートしていると確信しています。しかし、一般に、「なぜDeveloper Xは何をやったのですか?」と尋ねるスタックオーバーフローにはあまり適していません。確実に答えられるのはDeveloper Xだけです。この場合、私はDeveloper Xです。数年前にこのコードを書きました。他に誰も明確に答えることはできません。 – CommonsWare

+1

@CommonsWare主要なフレームワークコードの作成者が説明しているように見えるのは、まあまあです。 – chrylis

答えて

0

変数のみその​​ブロックでアクセスされているので、volatileは、必要とされません。

しかし、​​は、あまりに高すぎることがあります。特に、そのメソッドへの多数の呼び出しが変数を読み込んで復帰することを考慮してください。​​で読み込みをすべて囲むには重すぎると感じます。そこで我々は、​​のほとんどの時間

を回避し、いわゆるダブルチェックパターンを、持っている
if(var==null) 
    synchronized(lock) 
     if(var==null)   // double-check 
      var = something 
return var 

(OPのコードサンプルは、しかし、ロック、ダブルチェックされていない、それはすべての時間のロックです。)

では倍増通常はvarvolatileである必要があります。オブジェクトに割り当てられたオブジェクトがプリミティブ(intなど)または不変(Stringなど)の場合、不揮発性はOKです。

また、不揮発性の場合があります。これには、ユースケースの慎重な評価が必要です。たとえば、java.util.concurrent(例:ReentrantLock)のすべてのユーティリティクラスは、「安全でない公開」に耐えられるように設計されています。二重チェックロックパターンで使用される場合、それらはvolatileである必要はありません。 WakeLockのソースコードを見ると、ダブルチェックロックのいずれかがvolatileである必要はありません。

もちろん、これはあまりにも多すぎます。だから、あなたが何をしているのか正確に分からない限り、安全に遊んで、volatileを使ってください。 A volatile読み取りは普通の読み取りよりもそれほど高価ではありません。

+1

また、AndroidがJava Memory Modelに準拠していないため、「揮発性」はAndroidのすべてのバージョン(特に古いDalvik VMの実装)でメモリの可視性を保証するものではありません。揮発性のキーワードがVMによって本質的に無視されたので、私は過去にそれを焼き尽くしました。あなたはAndroid上で揮発性のセマンティクスが必要な場合は、 "AtomicReference"または他のjava.util.concurrent AtomicXXXクラスを使用することをお勧めします。 – GameSalutes

+0

@GameSalutes - that sucks :)私は、グーグルがどれくらいのお金と才能をもっているのか、サンよりも優れた仕事をしていると思っていました。 – ZhongYu

+0

確かに。少なくとも原子クラスは、実装者が遵守しなければならない契約を提供しています。私はAndroidで成功させて使用して以来、揮発性を使用していません。ここで少しそれについて説明するスレッドです:http://stackoverflow.com/questions/6973667/dalvik-vm-java-memory-model-concurrent-programming-on-android – GameSalutes

関連する問題