不需要新变量声明的小函数的java可读性
我需要一些关于小方法的代码结构的建议。 下面是来自JavaAPI的一个方法。收藏。阶级
private static Random r;
public static void shuffle(List<?> var0) {
Random var1 = r;
if (var1 == null) {
r = var1 = new Random();
}
shuffle(var0, var1);
}
代码可以重写为
private static Random r;
public static void shuffle(List<?> var0) {
if (r == null) {
r = new Random();
}
shuffle(var0, r);
}
我想知道第二种方法是否有我没有的副作用。 在什么情况下,一方会选择一种特定的方式而不是另一方
# 1 楼答案
原始源代码如下所示
以及设计背后的要点提示。该代码使用共享字段
r
,并且不是线程安全的,但其设计方式使其后果是“无害的”显然,您不应该以这种方式设计软件。对于某些他们认为性能很重要的软件,这就留给了专家们。(实际上,
shuffle
方法可能不属于这一类)那么你的选择呢
丢失线程安全性的后果不会是无害的。测试
r == null
和后续调用shuffle(var0, r)
具有对r
的不同读取,虽然应该只有从初始null
到初始化的Random
实例的转换,但是在没有使用线程安全机制的情况下,读取和写入可能会被认为是无序的,因此当发生并发写入时,r == null
可以计算为false
,而随后的shuffle(var0, r)
读取null
这并不意味着这个变体是错误的。如果您将您的方法或包含的类记录为线程不安全,并且在被不同的线程使用时需要外部同步,那么不会有任何错误
Collections
类的shuffle
方法将r
的值读入局部变量,以确保rnd == null
测试和shuffle(list, rnd)
调用将使用相同的值。由于这可能会读取对另一个线程创建的Random
实例的引用,因此它依赖于Random
实例本身是线程安全的这一事实,否则,racy读取可能会显示不一致的对象状态读操作仍然可能会遗漏先前由另一个线程写入的值,或者在读取
null
和随后写入对新创建的Random
实例的引用之间发生另一个线程的写入。因此,多个线程可能会在这里构造和使用不同的Random
实例,这被认为是“无害”的结果如前所述,您不应复制此模式。相反,您可以选择线程安全或无线程安全,并将您的代码记录下来