Effective Java 第 83 条的示例代码是不是错的?

2023-12-28 17:03:16 +08:00
 Bronya

关于多线程的,书中给了一个延迟初始化的例子,用的是双重检查方式:

// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;

private FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized (this) {
            if (field == null) // Second check (with locking)
                field = result = computeFieldType();
        }
    }
    return result;
}

这里是原书第三版的第 83 条:

这里面的局部变量 result 不是很好理解,而且我在 JDK 21 下跑出来是可能取到 null 的,求大佬解释一下~

破案了,就是错的,看这里https://github.com/jbloch/effective-java-3e-source-code/issues/8,issues 里面给出了解决方法:

private FieldType getField() {
	FieldType result = field;
	if (result == null) { // First check (no locking)
		synchronized (this) {
			if (field == null) // Second check (with locking)
				field = result = computeFieldValue();
			else
				result = field;
		}
	}
	return result;
}
2091 次点击
所在节点    Java
7 条回复
beneo
2023-12-28 17:07:39 +08:00
这个语法我都没见过了

field = result = computeFieldType();
cover
2023-12-28 17:17:54 +08:00
自问自答?
cover
2023-12-28 17:20:01 +08:00
就是两个线程一起 synchronized 锁的时候,field 初始化成功了,但是 result 没值,后进 synchronized 那根线程拿到了 null ,修复方案也显而易见,就是让后进的线程也拿到已经被前置线程赋值完成的 field ,其实我觉得最后返回 field 更加方便。
Bronya
2023-12-28 17:22:19 +08:00
@cover #2 刚开始没找到那个 ussues ,发完帖子之后又搜索了一下,发现原来真的是作者搞错了,然后赶紧编辑了一下,看起来就像自问自答了😂
flython6
2023-12-28 17:27:19 +08:00
这个例子确实是错的返回 result
但是我纠结的是为什么要使用局部变量……解释感觉跟没说的一样
flython6
2023-12-28 17:32:16 +08:00
@cover 哦我懂作者意思了,确实 else 直接返回 field 也可以,还省了一步赋值操作
但是最外面返回 result 主要是想要避免 volatile 变量读取时的缓存行失效,这样可以提升性能(着实是没什么用处的提升)
如果 DCL 最外层检测失败,或者修改后代码没进入 else ,也可以确保最少限度地访问 field (因为每次访问 volitale 都会使缓存行失效从而从主内存加载最新变量副本到工作缓存)

我理解应该是这个意思,欢迎指正
kneo
2023-12-28 21:44:06 +08:00
别用这种方法,古老而易错。在我看来这是一个 anti pattern ,应该从 effective java 里拿掉。
搜索一下 enum singleton 。或者,就用一个普通的锁。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1004173

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX