gpt4 book ai didi

java - 我使用 AtomicBoolean 的线程安全类有什么问题

转载 作者:行者123 更新时间:2023-12-01 07:28:15 27 4
gpt4 key购买 nike

我有一个简单的类,我想使用 AtomicBoolean 测试它的线程安全性。如果测试的线程超过 2 个,则它不起作用。它在某些线程的 doSome 方法中抛出 NullPointerExcetion:有人可以告诉我我错了什么吗?谢谢。

package jcafe.common.utils;

import java.util.concurrent.atomic.AtomicBoolean;

public class ThreadSafeTest {

private final AtomicBoolean initialized = new AtomicBoolean(false);

private Object lazyObject = null;

protected void initialize() {
if (initialized.compareAndSet(false, true)) {

// Some other expensive init here
// Some other expensive init here

this.lazyObject = new Object();
}
}

public void doSome() {
initialize();

// NullPointerException here: this.lazyObject = null
System.out.println(this.lazyObject.toString());
}

public static void main(String[] args) {
final ThreadSafeTest test = new ThreadSafeTest ();

for (int i = 0; i < 100; i++) {
Thread t = new Thread(new Runnable() {

@Override
public void run() {
test.doSome();
}
});
t.start();
}
}
}

最佳答案

您没有正确完成锁定。您确保只有 1 个线程正在访问 initialized 变量(因为它是一个 AtomicBoolean),但是一旦进行该检查,就不再发生同步。

此时线程 T1 进入,检查 initialized 的值并将其设置为第一个线程。线程 T2 可能会出现,检查 initialized 的值,并且不进入 if block 。但此时不能保证 lazyObject 已初始化。因此,当 T1 处于 sleep 状态时(因此 lazyObject 尚未设置),T2 从该方法返回并尝试打印 lazyObject

解决此问题的最简单方法是,不要使用 AtomicBoolean,使方法同步并使字段可变。无论您在何处设置值,都应该在同步块(synchronized block)中进行。

public class ThreadSafeTest {

private volatile boolean initialized = false;

private volatile Object lazyObject = null;

protected synchronized void initialize() {
if (!initialized) {
initialized = true;
// Some other expensive init here
this.lazyObject = new Object();
}
}
....
}

或者,您可以在构建时设置值并将其定为最终值。如果所有字段都是不可变的,那么它将是线程安全的。

关于java - 我使用 AtomicBoolean 的线程安全类有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20848782/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com