Java 线程安全 - 多个原子操作? [英] Java thread safety - multiple atomic operations?

查看:121
本文介绍了Java 线程安全 - 多个原子操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是一个非开发者,想成为开发者,所以我的问题可能非常简单!

我只是在测试 Java 多线程的东西,这不是真正的代码.我想知道如何在 Java 中同时更新两个成员变量,以防我们希望它们同步.举个例子:

公共类测试{私有映射<字符串,布尔值>itemToStatus = new ConcurrentHashMap<>();私有集items = ConcurrentHashMap.newKeySet();public static void main(String[] args){(new Testing()).start("ABC");}公共无效开始(字符串名称){如果(名称.等于(ABC")){itemToStatus.put(name, true);items.add(name);}}}

在那种情况下(当然,想象一下多线程)我希望能够保证对 itemsitemToStatus 的任何读取总是返回相同的.

所以,如果代码在itemToStatus.put(name, true)行,其他线程询问items.contains(name),则返回false.另一方面,如果其他线程询问 itemToStatus.containsKey(name); 它将返回 true.我不希望那样,我希望它们都给出相同的值,如果这有意义的话?

我怎样才能使这两个更改原子化?这行得通吗?

if (name.equals("ABC")) {同步(这个){itemToStatus.put(name, true);items.add(name);}}

不过,我不明白为什么会这样.我认为这就是您需要锁或其他东西的情况?

干杯!

解决方案

仅同步写入是行不通的.您还需要同步(在同一对象上)对 itemsitemToStatus 集合的读取访问.这样,如果另一个线程正在更新这两个集合,则没有线程可以读取任何内容.请注意,以这种方式进行同步意味着您不需要 ConcurrentHashMapConcurrentHashSet;普通的 HashMapHashSet 会起作用,因为您提供了自己的同步.

例如:

public void start(String name) {如果(名称.等于(ABC")){同步(这个){itemToStatus.put(name, true);items.add(name);}}}公共同步布尔 containsItem(String name) {返回 items.contains(name);}公共同步布尔值 containsStatus(String name) {返回 itemToStatus.containsKey(name);}

这将保证 containsItem 返回的值也将被 containsStatus 返回,如果该调用被代替.当然,如果您希望返回值随时间保持一致(如首先调用 containsItem() 然后是 containsStatus()),则需要更高级别的同步.

I'm just a non-developer playing to be a developer, so my question may be extremely simple!

I'm just testing Java multi-threading stuff, this is not real code. I wonder how to make two member variables update at the same time in Java, in case we want them both in sync. As an example:

public class Testing
{
  private Map<String, Boolean> itemToStatus = new ConcurrentHashMap<>();
  private Set<String> items = ConcurrentHashMap.newKeySet();

  public static void main(String[] args)
  {
    (new Testing()).start("ABC");
  }

  public void start(String name) {
    if (name.equals("ABC")) {
      itemToStatus.put(name, true);
      items.add(name);
    }
  }
}

In that scenario (imagine multi-threaded, of course) I want to be able to guarantee that any reads of items and itemToStatus always return the same.

So, if the code is in the line itemToStatus.put(name, true), and other thread asks items.contains(name), it will return false. On the other hand, if that other thread asks itemToStatus.containsKey(name); it will return true. And I don't want that, I want them both to give the same value, if that makes sense?

How can I make those two changes atomic? Would this work?

if (name.equals("ABC")) {
    synchronised(this) {
        itemToStatus.put(name, true);
        items.add(name);
    }
}

Still, I don't see why that would work. I think that's the case where you need a lock or something?

Cheers!

解决方案

Just synchronizing the writes won't work. You would also need to synchronize (on the same object) the read access to items and itemToStatus collections. That way, no thread could be reading anything if another thread were in the process of updating the two collections. Note that synchronizing in this way means you don't need ConcurrentHashMap or ConcurrentHashSet; plain old HashMap and HashSet will work because you're providing your own synchronization.

For example:

public void start(String name) {
    if (name.equals("ABC")) {
        synchronized (this) {
            itemToStatus.put(name, true);
            items.add(name);
        }
    }
}

public synchronized boolean containsItem(String name) {
    return items.contains(name);
}

public synchronized boolean containsStatus(String name) {
    return itemToStatus.containsKey(name);
}

That will guarantee that the value returned by containsItem would also have been returned by containsStatus if that call had been made instead. Of course, if you want the return values to be consistent over time (as in first calling containsItem() and then containsStatus()), you would need higher-level synchronization.

这篇关于Java 线程安全 - 多个原子操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆