Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
安全访问多线程HashMap Java_Java_Multithreading - Fatal编程技术网

安全访问多线程HashMap Java

安全访问多线程HashMap Java,java,multithreading,Java,Multithreading,我有一个应用程序,它有一个ConcurrentHashMap,在本地存储存储在外部服务器上的数据副本。地图每隔几秒钟更新一次数据的新副本 我有一个循环,每隔几秒钟运行一次,它可以访问HashMap,并按照值的顺序将元素添加到数组中(它实际上做的更多,但这并不重要)。我的问题是,如果数据在创建数组的过程中发生变化,那么你可以在不同的地方有重复的键,或者留下一些完全的。 例如: // Map starts out like this 1 -> value1 2 -> value2 3 -

我有一个应用程序,它有一个ConcurrentHashMap,在本地存储存储在外部服务器上的数据副本。地图每隔几秒钟更新一次数据的新副本

我有一个循环,每隔几秒钟运行一次,它可以访问HashMap,并按照值的顺序将元素添加到数组中(它实际上做的更多,但这并不重要)。我的问题是,如果数据在创建数组的过程中发生变化,那么你可以在不同的地方有重复的键,或者留下一些完全的。 例如:

// Map starts out like this
1 -> value1
2 -> value2
3 -> value3
4 -> value4

// First 2 elements of array created
value1,value2

// Map is updated
3 -> value3
1 -> value1
2 -> value2
4 -> value4

// Last 2 elements of array created
value1,value2,value1,value4
如您所见,如果映射没有更改,则数组将是:“value1、value2、value3、value4”或“value2、value3、value1、value4”,如果它是在更新后运行的

下面是一些示例代码,它不是原始代码,但应该可以解释我的问题:

Map<Integer, String> mapThatGetsUpdated = new ConcurrentHashMap<Integer, String>();
String[] array = new String[mapThatGetsUpdated.size()];

for (int i = 0; i < mapThatGetsUpdated.size(); i++) {
    array[i] = mapThatGetsUpdated.get(i);
}
Map-mapThatGetsUpdated=new-ConcurrentHashMap();
String[]数组=新字符串[mapThatGetsUpdated.size()];
对于(int i=0;i

这样做的明显方法是复制映射,然后在使用后丢弃它,但我希望使用另一种方法,因为映射可能非常大,并且可能必须每秒复制几次。

这是一个问题,因为尽管
ConcurrentHashMap
是线程安全的,但您在执行复合操作时没有锁定

如果要保证状态一致,必须防止阅读时写入。

如果您希望读卡器在整个读操作中看到相同的信息,则必须:

  • 或者在读取期间阻止写入
  • 创建开始时正在读取的实体的快照
选项1(不要这样做)

在读取和写入期间,使用
synchronized
锁定
映射
,允许一次打开一个

这是许多新手程序员的第一次求助。它将有效地消除使用
ConcurrentHashMap
的任何好处

选项2(不要这样做)

在读取地图之前,复制地图

注意到迭代可能只是在做一些循环以外的事情,您可以尝试通过在
synchronized
块中复制映射并使用副本来最小化读取时的锁定

因为你经常阅读,这很可能也没有帮助

选项3

使用
原子参考
。将读取器中的引用复制到本地引用。编写器将引用替换为全新的
映射

此选项的可行性取决于正在进行的写作量。它被调用,如果写操作少而读操作多,则可以获得良好的吞吐量

它不需要显式锁定,但需要编写者做更多的工作

选项4

使用一个。将
Map
更改为
HashMap
并自己控制并发性(编写一个包装类)

使用
ReadLock
锁定读取,使用
WriteLock
锁定写入。你可以有很多读者,但一次只能有一个作者


将保证读取的一致性。

在更新或读取hashmap时,您能锁定(同步)hashmap吗?hashmap不保持插入顺序。@Braj编辑了这篇文章,使其更加清晰,我正在使用数组中索引的键。@immibis我认为这可能会破坏
ConcurrentHashMap
的作用吗?