使用来自其他类的公共静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?

Posted

技术标签:

【中文标题】使用来自其他类的公共静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?【英文标题】:synchronized method that use a public static HashTable from other class. How can I make this method thread safe? 【发布时间】:2015-10-28 10:35:56 【问题描述】:

假设我有一个使用其他类的公共静态哈希表的同步方法。我怎样才能使这个方法线程安全?据我了解,任何其他线程都可以更改此 HashTable,因为它在其他类中而不是在持有密钥的类(同步方法的类)中,不是吗?

【问题讨论】:

使用ConcurrentHashMap/HashSet等同步集合 Hashtable 已同步。 【参考方案1】:

您对 HashTable 的理解不正确。 HashTable 是同步的和线程安全的。

查看HashTable的源代码。所有公共方法都是同步的。

public synchronized V put(K key, V value) 

public synchronized V get(Object key)  
public synchronized boolean contains(Object value) 

【讨论】:

谢谢。如果映射在同步方法的同一类中并且映射是私有的,我可以使用 HashMap 代替吗?被同步方法使用时没有其他线程可以更改它? HashMap 未同步。如果你想同步,你可以使用Collections.synchronizedMap(map); 并在同步块中做这些事情。请参考:java67.blogspot.in/2015/02/… Collections.synchronizedMap 使方法调用原子化,它不会使其完全线程安全,您仍然需要同步块。对于线程安全操作,我更喜欢ConcurrentHashMap 这不是我的 qwestion 。如果地图在同步方法的 same 类中并且地图是 private ,我可以改用 HashMap 吗? 同步方法使用时没有其他线程可以更改它? 如果您只在同步块内部使用地图,那么您可以!确保您没有提供在外面访问地图的方式。【参考方案2】:

如果你想在同步方法中使用 HashMap,它可以工作,但前提是所有线程都使用包含方法和 HashMap 的类的相同实例em>,为了更清楚,请看下面的示例:

代码片段

public class SynchronizedCounter 
    private int c = 0;

    public synchronized void increment() 
        c++;
    

现在,如果所有线程都使用相同的 SynchronizedCounter 实例,我们确保每次只有一个线程在运行 increment() 方法,但如果每个线程都在实例化自己的 SynchronizedCounter 实例,那么方法不会是线程安全的。

Oracle官方说明here。

【讨论】:

但是 c 不是静态的,在您的示例中它是私有的.. 那么问题是什么?它是线程安全的,不是吗? 如果它是静态公共的,我们必须使用 Atomic Integer ,不是吗? 事件如果你的 HashMap 是静态的,这不会改变同步方法的行为,如果你的线程使用包含你的 HashMap 的类的同一个实例,那么同步方法将只允许一个线程每次运行该函数,但是,如果它们使用不同的实例,则该方法不会阻塞其他线程,无论您的 HashMap 是否为静态。 没有因为 HashMap 是静态的,所以它对所有实例都是一样的。 是的,我的意思是如果它不是静态的..所以如果它是静态的,那么使用相同的实例很重要,如果不是,则不重要

以上是关于使用来自其他类的公共静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?的主要内容,如果未能解决你的问题,请参考以下文章

类的公共成员及其访问

如何在Azure VM上配置IIS站点以接受来自其他外部IP地址的请求?

从单独的类文件访问公共静态类的状态

Fragments 作为静态内部类与独立公共类的设计逻辑是啥?

深入理解java:2.3.3. 并发编程concurrent包 之容器ConcurrentHashMap

Hashtable与HashMap有啥区别?