黑白内部锁定,客户端锁定和外部锁定有什么区别?
创建线程安全类的最佳方法是什么?
哪种锁定是首选&为什么?
我强烈建议您阅读 Brian Goetz 的“ Java Concurrency In Practice ”。这是一本很好的书,可以帮助你理解所有关于并发的概念!
关于你的问题,我不确定我是否能全部回答,但我可以试一试。大多数时候,如果问题是“什么是最好的锁定方式”等,答案总是取决于你试图解决什么问题。
问题一:
您在此处尝试比较的内容并不完全可比;
Java 提供了一种内置的锁定机制,即synchronized
块。每个对象都可以隐式地充当同步锁;这些内置锁称为内在锁。
该术语的有趣之intrinsic
处在于锁的所有权是每个线程而不是每个方法调用。这意味着在给定时间只有一个线程可以持有锁。您可能还会发现有趣的是术语reentrancy
,它允许同一个线程再次获取同一个锁。内在锁是可重入的。
客户端锁定,如果我理解你的意思,是不同的东西。当您没有线程安全类时,您的客户需要注意这一点。他们需要持有锁,这样他们才能确保没有任何竞争条件。
外部锁定是,而不是使用同步块的内置机制,它为您提供隐式锁定以专门使用显式锁定。这是一种更复杂的锁定方式。有很多优点(例如,您可以设置优先级)。一个好的起点是关于锁的 java 文档
问题 2: 这取决于 :) 对我来说最简单的方法是尝试保持一切不可变。当某些东西是不可变的时,我不再需要关心线程安全了
问题3: 我在你的第一个问题上回答了它
显式 - 使用锁接口等并发锁实用程序进行锁定。例如 -ConcurrentHashMap
使用synchronized
.
客户端锁定 - 像这样的类ConcurrentHashMap
不支持客户端锁定,因为 get 方法没有使用任何类型的锁定。因此,尽管您像同步(对象)一样对其对象进行了锁定,ConcurrentHashMap
但其他一些线程仍然可以访问ConcurrentHashMap
.
具有所有设置获取方法的类显式或内在锁支持客户端锁定。当一些客户端代码出现并锁定该对象时。下面是向量的例子
public static Object getLast(Vector list) {
synchronized (list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
}
public static void deleteLast(Vector list) {
synchronized (list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
}
以下是一些讨论不同锁定方案的链接:
我不知道创建线程安全类是否有“最佳”方法,这取决于您要达到的目标。通常你不必使整个类线程安全,只保护不同线程都可以访问的资源,例如公共列表等。