- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因为,statckoverflow 不允许在原始问题中向您的问题添加更多内容(您只能添加评论,不能添加代码)我在这里问我的原始问题的顺序问题: Can we use Synchronized for each entry instead of ConcurrentHashMap?
问题很简单,我不知道为什么我之前可能很多人都遇到过这样一个简单的问题我要花这么多时间:/
问题是:我有一个 hashmap,我希望当一个线程正在处理 hashMap 的一个条目时,没有任何其他线程访问该对象,并且我不想锁定整个 hashMap。
我知道 java 提供了 ConcurrentHashMap,但是 ConcurrentHashMap 并没有解决问题,当你想做比简单的 put 和 get 更复杂的事情时。即使是像 merge 这样新添加的功能(在 Java 8 中)也不足以应对复杂的场景。
例如:
假设我想要一个将字符串映射到 ArrayList 的 HashMap 。然后例如假设我想这样做:对于键 k,如果有任何条目,则将 newString 添加到其 ArrayList,但如果没有 k 的条目,则为 k 创建条目,使其 ArrayList 具有 newString。
我想我可以这样做:
ArrayList<String> tm =new ArrayList<String>();
tm.add(newString);
Object result = map.putIfAbsent(k, tm);
if (result != null)
{
map.get(k).add(newString);
}
但是它不起作用,为什么?假设 putIfAbset 返回 null 以外的东西,那么这意味着 map 已经有一个带有键 k 的条目,所以我将尝试将 newString 添加到已经存在的条目的 ArrayList 中,但是在添加之前,另一个线程可能会删除该条目,并且然后我会得到 NullPointerException!
因此,我发现很难正确编写此类代码。
但我在想,如果我能简单地锁定那个条目,生活就会很精彩!
在我之前的帖子中,我提出了一些非常简单的建议,实际上消除了对 concurrentHashMap 的需求,并提供了入门级锁定,但有人说这不是真的,因为 Long 不是不可变的……我没有很好地理解它.
现在,我实现并测试了它,它对我来说看起来不错,但我不知道为什么其他更有经验的开发人员告诉我它不是线程安全的:(
这是我测试过的确切代码:
主线程:
import java.util.HashMap;
public class mainThread {
public static HashMap<String, Long> map = new HashMap<String, Long>();
public static void main (String args[])
{
map.put("k1", new Long(32));
synchronized(map.get("k1"))
{
Thread t = new Thread(new threadA());
t.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
线程A:
public class ThreadA implements Runnable {
@Override
public void run() {
mainThread.map.put("k2", new Long(21));
System.out.println(mainThread.map.get("k2"));
synchronized (mainThread.map.get("k1")) {
System.out.println("Insdie synchronized of threadA");
}
}
}
效果很好!它打印 21,5 秒后,mainThread 释放 map.get("k1") 的锁,它打印 "Insdie synchronized of threadA"
那么,为什么使用这种简单的方法我们不能提供入门级锁定?!为什么并发应该那么复杂 Lol(开玩笑)
最佳答案
首先,据我所知,没有提供入门级锁定的标准 map 实现。
但我认为您可以避免这样做。例如
更新 ... 更正错误
ArrayList<String> tm = new ArrayList<String>();
ArrayList<String> old = map.putIfAbsent(k, tm);
if (old != null) {
tm = old;
}
synchronized (tm) {
// can now add / remove entries and this will appear as an atomic
// actions to other threads that are using `synchronized` to
// access or update the list
tm.add(string1);
tm.add(string2);
}
是的,另一个线程可能会在这个线程(可能)插入它和这个线程锁定它之间更新 hashmap 条目中的列表。不过,那没关系。 (更正的)putIfAbsent
和随后的测试确保每个人都将使用和锁定相同的列表。
(假设:所有线程在插入/更新条目时都使用此逻辑。)
如果列表变空,则原子删除列表很困难,但我认为通常没有必要这样做。
更新 2
有一个更好的方法:
ArrayList<String> tm = map.computeIfAbsent(k, ArrayList::new);
synchronized (tm) {
...
}
(感谢斯图尔特)
更新 3
We can do it with merger too.
也许,是的。像这样:
ArrayList<String> tm = new ArrayList<String>;
tm.add(...);
...
map.merge(key, tm, (oldV, newV) -> {oldV.addAll(newV); return oldV});
缺点是您正在双重处理 tm
的所有元素;即添加到 2 个单独的列表(其中一个你扔掉)。
但你也可以这样做:
map.merge(key, tm, (oldV, newV) -> {
oldV.removeAll(newV);
return oldV.size() == 0 ? null : oldV}
);
让我担心的是 javadoc没有明确声明值 oldV
将在发生这种情况时被锁定。它说:
"The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress ..."
...但它没有明确说明在发生这种情况时值 存在互斥。 (例如,将此方法与 putIfAbsent
/computeIfAbsent
和显式 synchronized
block 混合使用很可能是危险的。锁定很可能是不同的对象。)
关于java - 如何在 HashMap 中实现入门级锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38494042/
Hive —— 入门 Hive介绍 Apache Hive是一款建立在Hadoop之上的开源数据仓库系统,可以将存储在Hadoop文件中的结构化、半结构化数据文件映射为一张数据库表,基于表提供了一
HBase —— 入门 HBase介绍 HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”
零:前端目前形势 前端的发展史 HTML(5)、CSS(3)、JavaScript(ES5、ES6):编写一个个的页面 -> 给后端(PHP、Python、Go、Java) ->
在本教程中,您将了解在计算机上运行 JavaScript 的不同方法。 JavaScript 是一种流行的编程语言,具有广泛的应用程序。 JavaScript 以前主要用于使网页具有交
我曾经是一个对编程一窍不通的小白,但因为对互联网世界的好奇心和求知欲的驱使,我踏入了编程的殿堂。在学习的过程中,我发现了一门神奇的编程语言——Python。Python有着简洁、易读的语法,让初学者能
嗨,亲爱的读者们! 今天我要给大家分享一些关于Python爬虫的小案例。你是否曾为了获取特定网页上的数据而烦恼过?或者是否好奇如何从网页中提取信息以供自己使用?那么,这篇文章将会给你一些启示和灵感。
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
我想创建一个像https://apprtc.appspot.com/?r=04188292这样的应用程序。我对 webrtc 了解一点,但无法掌握 google app-engine。如何为 java
我刚刚开始使用 Python 并编写了一个简单的周边程序。但是,每当我在终端中键入 python perimeter.py 时,都会收到以下错误,我不知道如何解决。 >>> python perime
Redis有5个基本数据结构,string、list、hash、set和zset。它们是日常开发中使用频率非常高应用最为广泛的数据结构,把这5个数据结构都吃透了,你就掌握了Redis应用知识的一半了
创建发布web项目 具体步骤: 1.在开发工具中创建一个dynamic web project helloword 2.在webContent中创建index.html文件 3.发布web应用到
如果你在 Ubuntu 上使用终端的时间很长,你可能会希望调整终端的字体和大小以获取一种良好的体验。 更改字体是一种最简单但最直观的 Linux 的终端自定义 的方法。让我
1. 前言 ADODB 是 Active Data Objects Data Base 的简称,它是一种 PHP 存取数据库的函式组件。现在 SFS3 系统 (校园自由软件交流网学务系统) 计划的
我对 neo4j 完全陌生,我很抱歉提出这样一个基本问题。我已经安装了neo4j,我正在使用shell“localhost:7474/webadmin/#/console/” 我正在寻找一个很好的例子
我正在阅读 ios 4 的核心音频,目的是构建一个小测试应用程序。 在这一点上,我对所有 api 的研究感到非常困惑。理想情况下,我想知道如何从两个 mp3 中提取一些样本到数组中。 然后在回调循环中
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是无关紧要的,因
我下载了 GNUStep并安装了它,但是我不确定在哪里可以找到 IDE。有谁知道什么程序可以用作 GNUStep IDE/从哪里获取它们?否则,有没有人知道有关如何创建和编译基本 GNUStep 程序
我正在尝试开始使用 Apache Solr,但有些事情我不清楚。通读tutorial ,我已经设置了一个正在运行的 Solr 实例。我感到困惑的是 Solr 的所有配置(架构等)都是 XML 格式的。
请问有没有关于如何开始使用 BruTile 的文档? 我目前正在使用 SharpMap,我需要预缓存切片以加快进程 最佳答案 我今天正在研究这个:)Mapsui项目site严重依赖 SharpMap
尽我所能,我无法让 CEDET 做任何事情。 Emacs 24.3。我下载了最新的 CEDET 快照。我从他的底部(不是这样)Gentle Introduction 中获取了 Alex Ott 的设置
我是一名优秀的程序员,十分优秀!