Java – do operations on ThreadLocal have to be synchronized?
This is the code I stumbled upon:
class TransactionContextHolder { private static final ThreadLocal<TransactionContext> currentTransactionContext = new NamedInheritableThreadLocal<TransactionContext>( "Test Transaction Context"); static TransactionContext getCurrentTransactionContext() { return currentTransactionContext.get(); } static void setCurrentTransactionContext(TransactionContext transactionContext) { currentTransactionContext.set(transactionContext); } static TransactionContext removeCurrentTransactionContext() { synchronized (currentTransactionContext) { TransactionContext transactionContext = currentTransactionContext.get(); currentTransactionContext.remove(); return transactionContext; } }
}
The type of currenttransactioncontext field is ThreadLocal, which is the only field in the class
In my opinion, there is no need for synchronization here, because the value stored in ThreadLocal is associated with a specific thread, so it is not a shared state In addition, I think it will affect the performance, because the currenttransactioncontext itself is shared, only one thread is allowed to enter the block, and many threads can execute in parallel without affecting the correctness
Do you need synchronization here?
Solution
Generally speaking, because thread safety is an attribute of the whole program, it is difficult to ensure thread safety only through a small part of the program, and synchronized can coordinate the behavior of many different parts of the program
For example: maybe there are some other code fragments elsewhere that use crazy unsafe reflection to try to check and / or change the content of ThreadLocal. If you change ThreadLocal without locking, will this be interrupted?
But in fact, you're right: there's never any reason to synchronize on a ThreadLocal instance except perhaps in its initialvalue method ThreadLocal itself is a thread safety mechanism, which can better manage its thread safety
(hat tip to Margaret bloom. Used to point out the initialvalue case)