4 回答
TA贡献1982条经验 获得超2个赞
那么上面的代码只是同步了整个 syncHashMap 类还是其中的每个方法?
不确定同步整个 syncHashMap 类及其中的每个方法是什么意思。
如果你查看 method 的源代码Collections.synchronizedMap(hashMap)
,你会发现它使用synchronized
关键字来修饰原始映射的每个方法。这意味着对于装饰后的地图对象,您一次只能调用其方法之一。但是不同的地图,你可以一次调用它们。
你可以在这里找到它们的用法。ConcurrentHashMap 与同步 HashMap
TA贡献1852条经验 获得超1个赞
有几个术语涉及您所询问的主题。
同步化
有许多接口和类可以帮助您在线程之间同步代码。一个Semaphore,一个CyclicBarrier或像BlockingQueue这样的同步集合。有关这些类的列表,请参阅java.util.concurrent包。
synchronized
块也是一种同步方式,但正确使用它需要更多经验。
互斥量
不同的语言(和库)以不同的方式实现标准互斥锁。这个想法保持不变——为了继续执行特定代码,一个互斥令牌,必须获得一个互斥体。在 Java 中,这种获取发生在进入synchronized
块之前。
线程安全
简而言之,当一个类的所有方法可以从任意数量的线程以任意顺序同时访问时,它就是线程安全的。有几种方法可以实现线程安全。例如,字符串是线程安全的。它们不是同步的,但它们是不可变的,这也会导致线程安全。所有Collections.synchronized*()
方法都返回集合的线程安全包装器,前提是所有未来*(*请参阅先发生关系)对它们的访问都是通过这些包装器执行的(这就是为什么初学者只调用Collections.synchronized*()
onnew
对象是一个很好的规则。
答案
根据前面段落的知识,回答你的问题:不,它不同步一个类。它根本不会改变原来的Collection
实现。但是,它确实为该类创建了一个读写线程安全的同步可变代理。
TA贡献1854条经验 获得超8个赞
在回答您的问题之前,让我们重申一些同步的基础知识
同步总是在一个对象/实例上。每个同步实例都由一个锁(称为互斥锁)保护。
任何在对象上调用同步方法的线程都必须先获取该锁,然后再调用该方法。
调用未同步方法的原因不需要此锁获取。
回答你的问题:
那么上面的代码只是同步了整个 syncHashMap 类还是其中的每个方法?
是的,它确实。在这里查看Collections.SynchronizedMap 的源代码即可。注意几乎每个方法都有同步(互斥)块。
如果我们可以在多线程场景中简单地使用线程安全的集合,例如 ConcurrentHashMap 或 SynchronizedMap,那么 Collections 类中的 Collections.synchronizedMap(hashMap) 和其他类似方法的需求是什么?
好吧,同步每个方法(包括只读类型的方法)都有缺点。它不必要地减慢了读取操作,因此您的观察是正确的,即使用诸如 ConcurrentHashMap 之类的实现,它只锁定正在修改集合的方法。只读方法不同步,因此在具有并发读/写操作的多线程场景中速度更快。
Collections.synchronizedMap 提供的唯一优势是保留输入键的顺序。因此,当您需要时,您可以使用 Collections.synchronizedMap。
添加回答
举报