Aquire Singleton class Instance Multithread

。_饼干妹妹 提交于 2019-12-02 02:16:11
David Heffernan

Your design does not work and this can be seen even without any understanding of what InterlockedCompareExchange does. In fact, irrespective of the meaning of InterlockedCompareExchange, your code is broken.

To see this, consider two threads arriving at the if statement in getInstance at the same time. Let's consider the three options for which branches they take:

  1. They both choose the second branch. Then you create two instances and your code no longer implements a singleton.
  2. They both choose the first branch. Then you never create an instance.
  3. One choose the first and the other chooses the second. But since there is no lock in the first branch, the thread that takes that route can read AObject before the other thread has written it.

Personally I'd use double-checked locking if I had to implement your getInstance function.

There is a technique called "Lock-free initialization" that does what you want:

interface

function getInstance: TObject;

implementation

var
   AObject: TObject;

function getInstance: TObject;
var
   newObject: TObject;
begin
   if (AObject = nil) then
   begin
      //The object doesn't exist yet. Create one.
      newObject := TObject.Create;

      //It's possible another thread also created one.
      //Only one of us will be able to set the AObject singleton variable
      if InterlockedCompareExchangePointer(AObject, newObject, nil) <> nil then
      begin
         //The other beat us. Destroy our newly created object and use theirs.
         newObject.Free;
      end;
   end;

   Result := AObject;
end;

The use of InterlockedCompareExchangePointer erects a full memory barrier around the operation. It is possible one might be able to get away with InterlockedCompareExchangeRelease to use release semantics (to ensure the construction of the object completes before performing the compare exchange). The problem with that is:

  • i'm not smart enough to know if Release semantics alone really will work (just cause a smarter person than me said they would, doesn't mean i know what he's talking about)
  • you're constructing an object, the memory barrier performance hit is the least of your worries (it's the thread safety)

Note: Any code released into public domain. No attribution required.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!