As I known, there are two common kinds of practices to ensure the thread safety of lazy-initialization:
It seems VCL uses the second practice. Is there any reason?
class function TEncoding.GetUTF8: TEncoding;
var
LEncoding: TEncoding;
begin
if FUTF8Encoding = nil then
begin
LEncoding := TUTF8Encoding.Create;
if InterlockedCompareExchangePointer(Pointer(FUTF8Encoding), LEncoding, nil) <> nil then
LEncoding.Free;
end;
Result := FUTF8Encoding;
end;
or is there any better method?
Thanks!
For the singleton pattern, double-checked locking is not needed: If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. C++11 and beyond also provide a built-in double-checked locking pattern in the form of std::once_flag and std::call_once :
In software engineering, double-checked locking (also known as "double-checked locking optimization") is a software design pattern used to reduce the overhead of acquiring a lock by testing the locking criterion (the "lock hint") before acquiring the lock. Locking occurs only if the locking criterion check indicates...
The double-checked locking pattern (DCLP) is a bit of a notorious case study in lock-free programming. Up until 2004, there was no safe way to implement it in Java. Before C++11, there was no safe way to implement it in portable C++. The pattern gained attention for the shortcomings it exposed in those languages, and people began to write about it.
Double-Checked Locking is widely cited and used as an efficient method for implementing lazy initialization in a multithreaded environment. Unfortunately, it will not work reliably in a platform independent way when implemented in Java, without additional synchronization.
There should not be much speed difference. In both approaches, global field is first checked if it is initialized and initialization is performed only when required. Therefore, most of the time the function will just do compare, jump, move, without any initialization.
When initialization is performed, InterlockedCompareEtc has two advantages over locking.
I find the InterlockedCompareEtc approach "neater" and use it in my code. But the locking would work equally well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With