相关疑难解决方法(0)

从多个线程获取java.util.HashMap中的值是否安全(无需修改)?

有一种情况会构建一个地图,一旦它被初始化,它将永远不会被再次修改.但是,它将从多个线程访问(仅通过get(key)).java.util.HashMap以这种方式使用是否安全?

(目前,我很高兴使用a java.util.concurrent.ConcurrentHashMap,并没有明确的需要提高性能,但我只是好奇,如果一个简单HashMap就足够了.因此,这个问题不是 "我应该使用哪一个?"也不是性能问题.相反,问题是"它会安全吗?")

java concurrency multithreading hashmap

135
推荐指数
8
解决办法
6万
查看次数

对于不同的密钥,HashMap是否是线程安全的?

如果我有两个多线程访问HashMap,但保证他们永远不会同时访问同一个密钥,那还能导致竞争条件吗?

java multithreading hashmap thread-safety

80
推荐指数
4
解决办法
5万
查看次数

指令重新排序和发生在java之前的关系

在Java Concurrency In Practice一书中,我们被告知可以通过编译器,JVM在运行时甚至由处理器重新排序程序的指令.因此,我们应该假设执行的程序不会以与我们在源代码中指定的顺序完全相同的顺序执行其指令.

但是,讨论Java内存模型的最后一章提供了一个先前发生的规则列表,指出了JVM保留了哪些指令排序.这些规则中的第一条是:

  • "程序顺序规则.线程中的每个操作都发生在程序顺序后面的该线程中的每个操作之前."

我相信"程序顺序"是指源代码.

我的问题:假设这个规则,我想知道什么指令可能实际重新排序.

"行动"定义如下:

Java内存模型是根据操作指定的,包括对变量的读取和写入,监视器的锁定和解锁,以及启动和连接线程.JMM定义了在程序中的所有操作之前调用的部分排序.为了保证执行动作B的线程可以看到动作A的结果(A和B是否出现在不同的线程中),必须在A和B之间的关系之前发生.在没有发生之前在两个之间进行排序操作,JVM可以随意重新排序.

其他提到的订单规则是:

  • 监控锁定规则.监视器锁定上的解锁发生在同一监视器锁定的每个后续锁定之前.
  • 易变变量规则.对每个后续读取同一字段之前发生对易失性字段的写入.
  • 线程启动规则.在线程上调用Thread.start会在启动线程中的每个操作之前发生.
  • 线程终止规则.线程中的任何操作都发生在任何其他线程检测到该线程已终止之前,可以通过成功从Thread.join返回,也可以通过Thread.isAlive返回false.
  • 中断规则.另一个线程上的线程调用中断发生在被中断的线程检测到中断之前(通过抛出InterruptedException,或者调用isInterrupted或中断).
  • 终结者规则.对象的构造函数的结束发生在该对象的终结器的开始之前.
  • 及物.如果A发生在B之前,B发生在C之前,那么A发生在C之前.

java concurrency multithreading java-memory-model

51
推荐指数
1
解决办法
1万
查看次数

Java多线程和安全发布

在阅读" 实践中的Java并发 "和" 实践中的OSGI "后,我发现了一个非常有趣的特定主题; 安全出版.以下内容来自JCIP:

要安全地发布对象,必须同时使对象的引用和对象的状态对其他线程可见.正确构造的对象可以通过以下方式安全发布:

  • 静态初始化程序初始化对象引用.
  • 将对它的引用存储到volatile字段中.
  • 将对它的引用存储到最终字段中.
  • 将对它的引用存储到由(同步)锁定正确保护的字段中.

我的第一个问题:有多少java开发人员知道这个(问题)?有多少真实世界的Java应用程序真正遵循这个,这真的是一个真正的问题吗?我有一种感觉,99%的已实现的JVM不是那种"邪恶",即一个线程不能保证(事实上它实际上(几乎)"不可能")看到陈旧数据只是因为引用不遵循上面的"安全出版成语".

java multithreading safe-publication

39
推荐指数
2
解决办法
8759
查看次数

在Java中,同时更改对HashMap读取的引用是安全的

我希望这不是一个愚蠢的问题......

我的代码中的代码类似于以下代码:

public class ConfigStore {

    public static class Config {

        public final String setting1;
        public final String setting2;
        public final String setting3;

        public Config(String setting1, String setting2, String setting3) {
            this.setting1 = setting1;
            this.setting2 = setting2;
            this.setting3 = setting3;
        }

    }

    private volatile HashMap<String, Config> store = new HashMap<String, Config>();

    public void swapConfigs(HashMap<String, Config> newConfigs) {
        this.store = newConfigs;
    }

    public Config getConfig(String name) {
        return this.store.get(name);
    }

}
Run Code Online (Sandbox Code Playgroud)

处理请求时,每个线程将使用getConfig()函数从存储中请求使用配置.但是,定期(最有可能每隔几天),使用swapConfigs()函数更新和交换配置.调用swapConfigs()的代码不会保留对它传入的Map的引用,因为它只是解析配置文件的结果.

  • 在这种情况下,volatile商店实例变量仍然需要关键字吗?
  • volatile关键字带来任何潜在的性能瓶颈,我应该知道的或可避免因为读取的速度大大超过写入的速度?

非常感谢,

java concurrency multithreading volatile

14
推荐指数
3
解决办法
4193
查看次数