【问题标题】:is class instance inside static method thread safe静态方法中的类实例是线程安全的吗
【发布时间】:2011-12-16 08:51:02
【问题描述】:

我有一个像下面这样的静态方法

 public static void foo(){
     final ClassA a = new ClassA();
 } 

我在 classA 中有两个哈希映射。

那些哈希映射线程安全吗...?

【问题讨论】:

标签: java multithreading concurrency thread-safety


【解决方案1】:

如果classA 内部的HashMaps 是非静态的(为每个新的ClassA() 创建新的),那么您可以从多个线程调用 foo 并保证只有一个线程将运行通过内部的HashMaps为该线程创建的 classA 实例。

【讨论】:

    【解决方案2】:

    目前尚不清楚您是要使用多线程访问对象a 内部的哈希映射还是使用多线程调用方法foo

    在第一种情况下,集合的线程安全与外部上下文无关,即它是否在静态上下文中创建。所以不,如果您尝试使用多个线程从对象a 访问哈希映射,则会导致意外行为。您需要使用 synchronized 块来规范对它们的访问。

    在第二种情况下,每个线程将在其堆栈上拥有不同的 foo 副本,并分配不同的 ClassA 实例。因此,它们不会发生冲突,因为它们将使用不同的HashMaps

    请说明您正在处理哪些案例。

    【讨论】:

      【解决方案3】:

      我不同意(我错过了什么)?

      在方法内部创建了一个新的 ClassA 实例。即使有多个线程访问该方法,每个线程也会有一个唯一的 HashMap 可以使用。

      如果 ClassA 是一个实例变量,那就不同了。此外,如果 ClassA 并发访问这些映射,则会出现线程问题。

      另外,如果地图是静态的,ClassA 的多个实例都可以访问它,是的,这将是 probamatic。

      【讨论】:

        【解决方案4】:

        HashMap 类不是线程安全的。

        请注意,此实现不同步。如果多个线程同时访问这个map,并且至少有一个线程在结构上修改了这个map,则必须对外同步

        但是,当您调用代码foo 时,您每次都会得到一个新的ClassA,因此调用foo 的两个不同线程将可以访问ClassA 的不同实例。假设ClassA 中的哈希图不是静态的或共享的,代码应该可以正常工作。

        【讨论】:

        • 但是新的操作是原子的吗?
        • 如果您担心线程安全映射,您可以使用 Collections.synchronizedMap 或 ConcurrentHashMap
        • @chance,是的,有一个系统范围的锁可以确保两个线程不能同时分配堆内存。
        【解决方案5】:

        您编写代码的方式将使您的静态方法可用于所有线程,因此每个线程都将获得自己的类对象。所以每个类都有自己的哈希映射。

        但是,如果您想为所有线程使用相同的哈希映射,请尝试将其设为 synchronized

        【讨论】:

          【解决方案6】:

          HashMap 不是线程安全的,但假设您从不发布实例 a 及其在 foo() 之外的两个哈希映射,那么这三个都被限制在一个线程中,并且不需要是线程安全的。

          如果您确实发布了a 或其哈希映射,或者哈希映射是ClassA 的静态成员,您应该确保线程安全。假设不存在涉及哈希映射或其他一些状态变量的不变量,您可以简单地使用ConcurrentHashMap 来完成此操作。如果有这样的不变量,您应该同步,最好尽可能接近状态变量,即在 ClassA 而不是 foo()

          【讨论】:

            猜你喜欢
            • 2018-02-09
            • 2010-11-08
            • 1970-01-01
            • 2016-07-16
            • 1970-01-01
            • 1970-01-01
            • 2013-06-19
            • 1970-01-01
            相关资源
            最近更新 更多