Question

En C #, le code suivant (de cette page ) peut être utilisé pour paresseusement instancier une classe singleton dans un fil de manière sûre:

  class Foo {
        private volatile Helper helper = null;
        public Helper getHelper() {
            if (helper == null) {
                lock(this) {
                    if (helper == null)
                        helper = new Helper();
                }
            }
            return helper;
        }
    }

Quel serait le fil équivalent en toute sécurité le code Delphi?


L'article mentionne également deux problèmes avec double verrouillage Démarrée Java:

  • il est possible que le nouvel objet est construit avant la référence d'aide est faite à un point au sens de l'objet nouvellement créé que deux objets sont créés
  • il est possible que la référence d'aide est faite à un point à un bloc de mémoire alors que l'objet est toujours en cours de création qui signifie qu'une référence à un objet incomplet sera retourné

Ainsi, alors que le code du C # et la version Java dans le regard de l'article mentionné presque identique, seule la version C # fonctionne comme prévu. Ce qui nous amène à la question supplémentaire si ces deux problèmes existent aussi dans une version Delphi de verrouillage revérifié?

Était-ce utile?

La solution

Utilisez System.TMonitor pour verrouiller l'instance d'objet dans un fil de manière sûre.

function TFoo.GetHelper(): THelper;
begin
  if not Assigned(FHelper) then
  begin
    System.MonitorEnter(Self);
    try
      if not Assigned(FHelper) then
        FHelper := THelper.Create();
    finally
      System.MonitorExit(Self);
    end;
  end;
  Result := FHelper;
end;

Pour plus d'aspect de référence à verrouillage mon objet ..., s'il vous plaît! de Allen Bauer . En fait, le représentant. Je déduis devrait aller à Allen.

Autres conseils

Bien sûr, il est toujours bon de rappeler que verrouillage revérifié est cassé . Cette question se révèle ne pas appliquer au modèle de mémoire x86 mais il vaut toujours la peine gardant à l'esprit pour l'avenir. Je suis sûr qu'il y aura la version Delphi à un moment qui se déroulera sur une plate-forme avec un modèle de mémoire qui est affligé par cette question.

Embarcadero ont commencé à utiliser une version sans verrou de ce modèle avec comparaison / échange agrafé. Par exemple:

class function TEncoding.GetUnicode: TEncoding;
var
  LEncoding: TEncoding;
begin
  if FUnicodeEncoding = nil then
  begin
    LEncoding := TUnicodeEncoding.Create;
    if InterlockedCompareExchangePointer(Pointer(FUnicodeEncoding), LEncoding, nil) <> nil then
      LEncoding.Free;
  end;
  Result := FUnicodeEncoding;
end;

Je sais que ce n'est pas une réponse à la question, mais il ne correspondait pas vraiment dans un commentaire!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top