gpt4 book ai didi

java - ThreadLocal.get() 返回 null,即使我之前初始化它

转载 作者:行者123 更新时间:2023-11-30 01:56:15 30 4
gpt4 key购买 nike

我觉得我可能误解了它应该如何工作。

我有这个代码:

public Timestamp startTransaction() {
cleanupTransactionContext();
Timestamp timestamp = getLatestTimestamp();
initThreadLocalVariables(timestamp);
return getTransactionContext().toString();
}

private Timestamp getTransactionContext() {
if (transactionContext == null) {
throw new BadTransactionStateException();
}
return transactionContext.get();
}

private void initThreadLocalVariables(Timestamp timestamp) {
setTransactionContext(timestamp);
}

private void setTransactionContext(Timestamp ts) {
if (this.transactionContext == null) {
this.transactionContext = new ThreadLocal<>();
}
this.transactionContext.set(ts);
}

据我了解,ThreadLocal.get() 永远不应该返回 null(来自 JDK):

/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}

因为我之前已经在 setTransactionContext 中明确设置了它,而它又调用 ThreadLocal.set,所以应该创建 map :

   /**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

但是,有时我会在以下位置遇到空指针异常:return getTransactionContext().toString();。其他时候它工作得很好,所以我怀疑存在某种竞争条件,我只是看不出它可能是什么。

PS:Timestamp 类如下所示:

public final class Timestamp {

private final long timeInMilliseconds;
private final long sequenceNumber;

}

但请注意,这是代码的简化版本,不包含多项检查以确保其不为空。 getLatestTimeStamp 值本身是正确的,不会被设置为 null。

最佳答案

正如 @shmosel 所指出的 - 问题是这段代码不是原子的:

private void setTransactionContext(Timestamp ts) {
if (this.transactionContext == null) {
this.transactionContext = new ThreadLocal<>();
}
this.transactionContext.set(ts);
}

因此两个线程可能正在创建 ThreadLocal 并互相干扰。将线程的创建移至变量声明本地可以解决该问题,因为 ThreadLocal 上的后续操作默认情况下是线程安全的。

关于java - ThreadLocal.get() 返回 null,即使我之前初始化它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54429504/

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