2011-06-29 85 views
1

我有一个像下面的类,我想知道,这将是线程安全的,或者主线程和Loader线程可能有自己的mCache副本,因此get(..)方法无法从缓存中检索任何内容,因为它是在加载程序线程中添加的?我需要标记这个volatile实例变量和线程

谢谢!

public class StackExample 
{ 
    private final ConcurrentHashMap<String, SoftReference<Bitmap>> mCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(); 

    private addToCache(String key, Bitmap bitmap) 
    { 
     mCache.put(key, bitmap); 
    } 

    private Bitmap getBitmap(String key) 
    { 
     if(mCache.contains(key)) 
     { 
      return mCache.get(key); 
     } 
     else 
     { 
      //add to loading queue 
     } 
    } 

    private class Loader extends Thread 
    { 
     @Override 
     public void run() 
     { 
      ...//check loading queue and load some images here 
      mCache.put(keyString, new SoftReference<Bitmap>(loadedBitmap)); 
     } 
    } 
} 
+0

您将只对所有线程都具有唯一的* mCache *,但您的代码仍然没有正确同步。你*可以*输入两次(或多于)* *添加到加载队列*你的代码的一部分为同一个*键*虽然从你的例子中并不完全清楚* getBitmap *从哪里调用(它显然是私有的!?)。 – SyntaxT3rr0r

+0

btw +1对你的问题和羞耻的人谁upvoted Jon Skeet的一个线路的答案,也没有upvoting很好的问题。 – SyntaxT3rr0r

+0

谢谢!是的,只是一个简单的例子,我知道你的意思是关于get方法:) – Dori

回答

4

变量是final的,所以它在构造函数(在这种情况下为空)返回之前对所有线程都是可见的。

+0

它是否可变无关紧要?最终的领域是否不会受到持有自己副本的线索的影响? – Dori

+1

@Dori:你认为会被复制什么? 'ConcurrentHashMap'是可变的,但是*设计*被多个线程使用而不锁定。 –

+0

对不起,我的印象可能是错误的,即所有变量都能够被使用它们的每个线程保留为本地副本,导致线程可能无法查看另一个线程对该变量所做的更改。在某些情况下,volatile关键字可以防止这种情况发生,但不会停止交错操作。我也认为同步停止交错操作,但我不确定它对变量的本地复制/缓存有什么影响 - 当sycnronised块启动/退出变量是否刷新/推送到主内存? – Dori

0

volatile表示每个线程都不会保留字段值的缓存。如果您能够写入mCache字段,那么如果您想确保另一个线程在由另一个线程设置后立即读取该字段时获得了新值,则可以声明该字段不稳定。

+0

从上面我认为这不适合的情况下,因为该字段只是一个参考和最终 – Dori

+0

确切。没有理由宣布它不稳定时,它不能改变 –