0

有一个快速的同步问题,这里是我有:法建立之前发生在阵列

一)Class1的已并发的哈希表定义如下:

ConcurrentMap<String, int[][]> map = new ConcurrentHashMap<String, int[][]>(); 

B)的Class2有一个线程,称为线程1。 Thread1创建一个Id并检查地图是否包含它。如果是,它将检索值(int [] []),修改内容并将其放回。如果没有,它会创建一个新的int [] []并存储它。这个检查 - >修改/创建的过程经常发生。

private class Thread1 implements Runnable{ 

      public void run(){ 
       //keepRunning is volatile 
       while(keepRunning){ 

        String id  = "ItemA"; 
        int[][] value = map.get(id); 

        //If value is null, create an int[][] and put it back as value for Id 
        //If value is not null, modify the contents according to some logic 
       } 
      } 
    } 

C)最后,我还有一个线程,称为线程2。这个线程需要一个id,检查映射是否有值。如果没有,没有任何反应。如果是这样,那么它总结int [] []中的值,并使用该数字进行一些计算(此处不作修改)。

我想弄清楚我的操作是否是原子操作。 b)中的操作很好,因为数组的创建/修改和插入地图仅限于一个线程(Thread1)。另外,由于插入到映射中会建立一个before-before动作,这将确保c)将在int [] []中看到更新的值。

但是,我不太确定如果Thread2在映射中查找相同的int [] []会发生什么情况,并尝试在Thread1修改它时对其进行总结。

我正确地认为Thread2会在int [] []中看到较旧(但未损坏)的值。原因是在Thread1完成将值放回地图之前,新的修改不会对Thread2可见。

非常感谢。

+0

正如旁注,你可能知道这是否,但它听起来像你试图实施生产者/ Consmer模式,看看http://docs.oracle.com/javase/tutorial/essential/并发/ guardmeth.html一些更多的想法 – MadProgrammer 2012-08-04 04:39:27

回答

1

您的操作不是原子的,线程2将试图在线程1修改它们时对值进行求和。

为避免这种情况,您需要复制原始修改副本并放回副本。

+0

嗨汤姆,谢谢。或者,我可不a)使用AtomicReferenceArray b)在b)中创建一个新数组(而不是从地图获取旧数组),然后使用它为特定Id更新地图。 – CaptainHastings 2012-08-06 12:15:50