下面这段代码存在并发陷阱???

发布于 2022-09-04 00:39:11 字数 989 浏览 20 评论 0

曾宪杰的《大型网站系统与Java中间件实践》第一章第1.2.2.3小节给出以下代码示例:

使用HashMap数据被进行统计;

public class TestClass
{
    private HashMap<String, Integer> map = new HashMap<>();
    
    public synchronized void add(String key)
    {
        Integer value = map.get(key);
        if(value == null)
        {
            map.put(key, 1);
        }
        else
        {
            map.put(key, value + 1);
        }
    } 
}

使用ConcurrentHashMap保存数据并进行统计;

public class TestClass
{
    private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
    
    public void add(String key)
    {
        Integer value = map.get(key);
        if(value == null)
        {
            map.put(key, 1);
        }
        else
        {
            map.put(key, value + 1);
        }
    } 
}

使用HashMap时,对add方法加锁,此时该方法是线程安全的,为何换为ConcurrentHashMap之后,原书中说存在并发陷阱???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雪化雨蝶 2022-09-11 00:39:11

为何换为ConcurrentHashMap之后,还要对add方法进行加锁???

public void add(String key)
    {
        Integer value = map.get(key);
        if(value == null)
        {
            map.put(key, 1);
        }
        else
        {
            map.put(key, value + 1);
        }
    } 

没加锁啊。

EDIT:

确实是存在并发陷阱。考虑一下这种情况:

  1. 线程A执行map.get(key);if(value == null)得到结果true, 然后交出cpu时间。

  2. 此时, 线程B也执行到同一个地方, 得到结果也为true, 因为线程A还没执行map.put(key, 1), 线程B执行map.put(key, 1), 此时map中已经有key的值了。

  3. 线程A得到CPU时间继续执行, 因为之前判断结果是true, 所以线程A又put了一次。最终的结果就是两个线程都执行了一次map.put(key, 1), 此时key的值依旧为1, 但实际上应该是2。

存在这个问题是原因是, ConcurrentHashMap的单个操作是原子性的, 但是你外部调用并不是原子性的, map.get 和 map.put 是两个操作, 相互独立的操作, 所以你如果要保证线程安全依旧需要在你的代码上加锁, 保证get和put两个操作的原子性。

尐籹人 2022-09-11 00:39:11

ConcurrentHashMap只保证在并发情况下其内部数据能够保持一致,而这一点HashMap是做不到的。

但是add方法并不是线程安全,因为这是一个典型的Check-Then-Act或者Read-Modify-Write

你可以思考这样一个问题,如果一个类里的所有field都是线程安全的类,那么这个类是否线程安全。答案显然是否定的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文