9

黑白内部锁定,客户端锁定和外部锁定有什么区别?

创建线程安全类的最佳方法是什么?

哪种锁定是首选&为什么?

4

3 回答 3

9

我强烈建议您阅读 Brian Goetz 的“ Java Concurrency In Practice ”。这是一本很好的书,可以帮助你理解所有关于并发的概念!

关于你的问题,我不确定我是否能全部回答,但我可以试一试。大多数时候,如果问题是“什么是最好的锁定方式”等,答案总是取决于你试图解决什么问题。

问题一:

您在此处尝试比较的内容并不完全可比;

Java 提供了一种内置的锁定机制,即synchronized块。每个对象都可以隐式地充当同步锁;这些内置锁称为内在锁

该术语的有趣之intrinsic处在于锁的所有权是每个线程而不是每个方法调用。这意味着在给定时间只有一个线程可以持有锁。您可能还会发现有趣的是术语reentrancy,它允许同一个线程再次获取同一个锁。内在锁可重入的。

客户端锁定,如果我理解你的意思,是不同的东西。当您没有线程安全类时,您的客户需要注意这一点。他们需要持有锁,这样他们才能确保没有任何竞争条件。

外部锁定是,而不是使用同步块的内置机制,它为您提供隐式锁定以专门使用显式锁定。这是一种更复杂的锁定方式。有很多优点(例如,您可以设置优先级)。一个好的起点是关于锁的 java 文档

问题 2: 这取决于 :) 对我来说最简单的方法是尝试保持一切不可变。当某些东西是不可变的时,我不再需要关心线程安全了

问题3: 我在你的第一个问题上回答了它

于 2014-12-06T23:52:20.867 回答
2

显式 - 使用锁接口等并发锁实用程序进行锁定。例如 -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);
    }
}
于 2013-10-30T20:16:22.727 回答
1

以下是一些讨论不同锁定方案的链接:

显式与内在

客户端锁定以及何时避免它

我不知道创建线程安全类是否有“最佳”方法,这取决于您要达到的目标。通常你不必使整个类线程安全,只保护不同线程都可以访问的资源,例如公共列表等。

于 2013-10-20T09:29:26.760 回答