KeyFactory 是线程安全的吗?
Is KeyFactory thread-safe?
有一项服务 class 需要从 X.509 编码的 public 密钥表示中生成 PublicKey
个实例。此 class 的一个实例将服务于多个线程。这样的做法对吗?
public class MyService {
private final KeyFactory rsaKeyFactory;
public MyService() throws NoSuchAlgorithmException {
rsaKeyFactory = KeyFactory.getInstance("RSA");
}
public PublicKey generatePublicKey(byte[] publicKeyBytes) throws GeneralSecurityException {
return rsaKeyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
}
}
即这里使用的 KeyFactory
实例是线程安全的吗? generatePublicKey()
方法可以被不同的线程同时调用。
Javadocs 似乎没有提到线程安全。
不,如果你想要线程安全,你必须使用同步块。
否,如果 the Javadoc makes no mention of thread-saftey then thread safety is not guaranteed ("synchronization is an implementation detail").[1] 将 synchronized
修饰符添加到您的 generatePublicKey
方法(或其他形式的锁定)以使其线程安全并且请务必添加 Javadoc 注释,指出它应该是线程安全的。
另请参阅:
Is there a standard annotation which should be added to the method's Javadoc to denote that a method should be called on a particular thread?
Characterizing thread safety(强调我的)
How many times have you looked at the Javadoc for a class, and wondered, "Is this class thread-safe?" In the absence of clear documentation, readers may make bad assumptions about a class's thread safety. Perhaps they'll just assume it is thread-safe when it's not (that's really bad!), or maybe they'll assume that it can be made thread-safe by synchronizing on the object before calling one of its methods (which may be correct, or may simply be inefficient, or in the worst case, could provide only the illusion of thread safety). In any case, it's better to be clear in the documentation about how a class behaves when an instance is shared across threads.
[...]
A class's thread-safety behavior is an intrinsic part of its specification, and should be part of its documentation. Because there is no declarative way of describing a class's thread-safety behavior (yet), it must be described textually. While Bloch's five-tier system for describing a class's degree of thread safety does not cover all possible cases, it's a very good start. Certainly we'd all be better off if every class included this degree of threading behavior in its Javadoc.
但也许……
看起来你的用途可能是(也就是说,正如猎人在评论中指出的那样,一旦你有一个 KeyFactory
实例,从多个线程调用 KeyFactory#generatePublic
可能是安全的) .
一点源代码潜水,KeyFactory.getInstance(String)
看起来像这样:[2] [3]
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException {
return new KeyFactory(algorithm);
}
依次调用:
private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
serviceIterator = list.iterator();
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException
(algorithm + " KeyFactory not available");
}
}
而 nextSpi
看起来像:
private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
synchronized (lock) {
// Truncated for brevity
}
}
KeyFactory#generatePublic
看起来像这样:
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException {
if (serviceIterator == null) {
return spi.engineGeneratePublic(keySpec);
}
// Truncated for brevity
}
看起来 class 确实在某些部分而不是其他部分进行了锁定,这(我想是有目的的)意味着他们考虑了线程安全性。这可能意味着他们打算在多个线程上为同一算法构建和使用工厂是安全的,但这也可能不是那个意思。您将需要详尽检查竞争条件的代码路径。
就是说,除了 Javadoc。
,请不要构建任何假设合同的东西
有一项服务 class 需要从 X.509 编码的 public 密钥表示中生成 PublicKey
个实例。此 class 的一个实例将服务于多个线程。这样的做法对吗?
public class MyService {
private final KeyFactory rsaKeyFactory;
public MyService() throws NoSuchAlgorithmException {
rsaKeyFactory = KeyFactory.getInstance("RSA");
}
public PublicKey generatePublicKey(byte[] publicKeyBytes) throws GeneralSecurityException {
return rsaKeyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
}
}
即这里使用的 KeyFactory
实例是线程安全的吗? generatePublicKey()
方法可以被不同的线程同时调用。
Javadocs 似乎没有提到线程安全。
不,如果你想要线程安全,你必须使用同步块。
否,如果 the Javadoc makes no mention of thread-saftey then thread safety is not guaranteed ("synchronization is an implementation detail").[1] 将 synchronized
修饰符添加到您的 generatePublicKey
方法(或其他形式的锁定)以使其线程安全并且请务必添加 Javadoc 注释,指出它应该是线程安全的。
另请参阅:
Is there a standard annotation which should be added to the method's Javadoc to denote that a method should be called on a particular thread?
Characterizing thread safety(强调我的)
How many times have you looked at the Javadoc for a class, and wondered, "Is this class thread-safe?" In the absence of clear documentation, readers may make bad assumptions about a class's thread safety. Perhaps they'll just assume it is thread-safe when it's not (that's really bad!), or maybe they'll assume that it can be made thread-safe by synchronizing on the object before calling one of its methods (which may be correct, or may simply be inefficient, or in the worst case, could provide only the illusion of thread safety). In any case, it's better to be clear in the documentation about how a class behaves when an instance is shared across threads.
[...]
A class's thread-safety behavior is an intrinsic part of its specification, and should be part of its documentation. Because there is no declarative way of describing a class's thread-safety behavior (yet), it must be described textually. While Bloch's five-tier system for describing a class's degree of thread safety does not cover all possible cases, it's a very good start. Certainly we'd all be better off if every class included this degree of threading behavior in its Javadoc.
但也许……
看起来你的用途可能是(也就是说,正如猎人在评论中指出的那样,一旦你有一个 KeyFactory
实例,从多个线程调用 KeyFactory#generatePublic
可能是安全的) .
一点源代码潜水,KeyFactory.getInstance(String)
看起来像这样:[2] [3]
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException {
return new KeyFactory(algorithm);
}
依次调用:
private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
serviceIterator = list.iterator();
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException
(algorithm + " KeyFactory not available");
}
}
而 nextSpi
看起来像:
private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
synchronized (lock) {
// Truncated for brevity
}
}
KeyFactory#generatePublic
看起来像这样:
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException {
if (serviceIterator == null) {
return spi.engineGeneratePublic(keySpec);
}
// Truncated for brevity
}
看起来 class 确实在某些部分而不是其他部分进行了锁定,这(我想是有目的的)意味着他们考虑了线程安全性。这可能意味着他们打算在多个线程上为同一算法构建和使用工厂是安全的,但这也可能不是那个意思。您将需要详尽检查竞争条件的代码路径。
就是说,除了 Javadoc。
,请不要构建任何假设合同的东西