Namenskonvention für dedizierte Thread-Sperrobjekte [geschlossen]

16

Eine relativ kleine Frage, aber ich konnte keine offizielle Dokumentation oder auch keine Blog-Meinung / -Diskussion dazu finden.

Einfach ausgedrückt: Wenn ich ein privates Objekt habe, dessen einziger Zweck darin besteht, für das Private zu dienen lock, wie bezeichne ich dieses Objekt?

class MyClass
{
    private object LockingObject = new object();

    void DoSomething()
    {
        lock(LockingObject)
        {
            //do something
        }
    }
}

Was sollen wir LockingObjecthier nennen? Berücksichtigen Sie auch nicht nur den Namen der Variablen, sondern auch, wie sie beim Sperren im Code aussieht.

Ich habe verschiedene Beispiele gesehen, aber anscheinend keinen soliden Ratschlag:

  1. Viele Verwendungen von SyncRoot(und Variationen wie _syncRoot).

    • Code - Beispiel: lock(SyncRoot) ,lock(_syncRoot)
    • Dies scheint von der äquivalenten SyncLockAussage von VB beeinflusst zu werden , der SyncRootEigenschaft, die in einigen ICollection-Klassen und einem Teil eines SyncRoot-Entwurfsmusters vorhanden ist (was vermutlich eine schlechte Idee ist).
    • Da ich mich in einem C # -Kontext befinde, bin ich mir nicht sicher, ob ich eine VBish-Benennung haben möchte. Schlimmer noch, bei VB benennt man die Variable genauso wie das Schlüsselwort. Ich bin mir nicht sicher, ob dies zu Verwirrung führen würde oder nicht.
  2. thisLockund lockThisaus den MSDN-Artikeln: C # lock Statement , VB SyncLock Statement

    • Code - Beispiel: lock(thisLock) ,lock(lockThis)
    • Ich bin mir nicht sicher, ob diese nur für das Beispiel minimal benannt wurden oder nicht
    • Etwas seltsam, wenn wir dies in einer staticKlasse / Methode verwenden.
    • BEARBEITEN: Der Wikipedia-Artikel über Sperren verwendet diese Benennung auch für sein Beispiel
  3. Mehrere Verwendungen von PadLock(von unterschiedlichem Gehäuse)

    • Code - Beispiel: lock(PadLock) ,lock(padlock)
    • Nicht schlecht, aber mein einziges Rindfleisch ist, dass es nicht überraschend das Bild eines physischen "Vorhängeschlosses" hervorruft, das ich normalerweise nicht mit dem abstrakten Threading-Konzept verbinde .
  4. Benennen der Sperre basierend auf der beabsichtigten Sperre

    • Code - Beispiel: lock(messagesLock) , lock(DictionaryLock),lock(commandQueueLock)
    • Im VB SyncRoot MSDN-Seitenbeispiel gibt es ein simpleMessageListBeispiel mit einem privaten messagesLockObjekt
    • Ich halte es nicht für eine gute Idee, die Sperre für den Typ zu benennen, um den Sie sie sperren ("DictionaryLock"), da dies ein Implementierungsdetail ist, das sich möglicherweise ändert. Ich bevorzuge die Benennung des zu sperrenden Konzepts / Objekts ("messagesLock" oder "commandQueueLock")
    • Interessanterweise sehe ich diese Namenskonvention zum Sperren von Objekten in Codebeispielen online oder auf StackOverflow sehr selten .
  5. (BEARBEITEN) Die C # -Spezifikation in Abschnitt "8.12 Die Sperranweisung" enthält ein Beispiel für dieses Muster und nennt es synchronizationObject

    • Code - Beispiel: lock(SynchronizationObject) ,lock(synchronizationObject)

Frage: Was halten Sie generell von der Benennung privater Sperrobjekte?

Vor kurzem habe ich angefangen, sie zu benennen ThreadLock(so ähnlich wie Option 3), aber ich stelle fest, dass ich diesen Namen in Frage stelle.

Ich verwende dieses Sperrmuster (im obigen Codebeispiel) häufig in meinen Anwendungen, daher hielt ich es für sinnvoll, eine professionellere Meinung / Diskussion über eine solide Namenskonvention für sie einzuholen. Vielen Dank!

Chris Sinclair
quelle

Antworten:

4

Ich habe es mir zur Gewohnheit gemacht, es SomeResourceLockdort zu nennen, wo SomeResourceSie die Sperre benötigen, um darauf zuzugreifen / zu aktualisieren, dh (verzeihen Sie Thread-Probleme, dies ist nur eine Illustration)

public class ProcessDataInQueue
{
    private static Queue<Data> _dataQueue = new Queue<Data>();
    private static object _dataQueueLock = new Object();

    public void AddOneItem(Data itemToAdd)
    {
        lock(_dataQueueLock)
        {
            _dataQueue.Enqueue(itemToAdd);
        }
    }

    public void ProcessOneItem()
    {
        Data itemToProcess = null;
        lock(_dataQueueLock)
        {
            itemToProcess = _dataQueue.Dequeue();
        }
        // ... process itemToProcess
    }
}

Ich bin auf diese Gewohnheit gestoßen, nachdem ich Klassen hatte, in denen ich möglicherweise mehrere Sperren für verschiedene Ressourcen habe. Daher benenne ich das Sperrobjekt basierend auf den Ressourcen, auf die der Sperrzugriff erfolgt. Manchmal kann ein Objekt mehrere Ressourcen sperren. In diesem Fall würde ich versuchen, die Namen in irgendeiner Weise zu berücksichtigen, sodass der Leser weiß, dass "auch andere Sperren für diese einzelnen Ressourcen mit dieser Sperre in Konflikt stehen".

Jimmy Hoffa
quelle
2
Ich finde das verwirrend, weil SynchronizationContextes etwas ganz anderes ist.
Svick
1
@svick Möglicherweise missbrauche ich den Begriff. Ich denke immer noch, dass es wichtig ist, genau zu wissen, welche Ressource gesperrt ist. Wenn dies jedoch sinnvoller ist, bearbeite ich dies, um anstelle von "SynchronizationContext" das Wort "Lock" vorzuschlagen.
Jimmy Hoffa
6

Ich nenne es normalerweise locker, aber da es privat ist, glaube ich, dass es ein etwas unwichtiges Implementierungsdetail ist. Erste Faustregel: Verwenden Sie die Standards Ihres Teams / Unternehmens. Wenn es keine gibt, dann mache bitte eine und benutze sie, aber wenn du sie machst, halte die Dinge einfach. Wenn Ihre Klasse über ein einzelnes Sperrobjekt verfügt, ist der Aufruf fooausreichend. Wenn Sie viele haben, könnte ein guter Geschäftsplan darin bestehen, zuerst das Design dieser Klasse zu überdenken, um festzustellen, ob es zu viele verschiedene Dinge bewirkt. Wenn nicht, wird der Name wichtig, wie in diesem vollständig erfundenen Beispiel:

public sealed class CustomerOrders
{
    private readonly object customerLocker = new object();

    private readonly object orderLocker = new object();

    public IEnumerable<Customer> Customers
    {
        get
        {
            lock (this.cutomerLocker)
            lock (this.orderLocker)
            {
                // stuff...
            }
        }

        set
        {
            lock (this.cutomerLocker)
            lock (this.orderLocker)
            {
                // other stuff...
            }
        }
    }

    public IEnumerable<Order> Orders
    {
        get
        {
            lock (this.orderLocker)
            {
                // stuff...
            }
        }

        set
        {
            lock (this.cutomerLocker)
            {
                // different stuff...
            }
        }
    }
}
Jesse C. Slicer
quelle
2
Ich stimme einem solchen Benennungsstil für mehrere Schließmechanismen voll und ganz zu. Auch ich hatte etwas sehr ähnliches wie diesen Stil, als ich eine Klasse mit zwei Schließfächern implementierte (auch später überarbeitet)
Chris Sinclair
2

Ich habe immer lck_ verwendet. Auf diese Weise sollten Sie, wenn Sie die Tastenkombination Strg + F "Lck" drücken, nur die Sperren finden, während "Sperre" auch Dinge wie "Uhr" findet.

Dinge wie lockThis und Padlock eignen sich gut für Uni-Portfolios, aber für richtige Projekte sollten Sie wirklich semantische Namen verwenden, damit Sie beim Betrachten der Deklarationen wissen, was das Objekt tatsächlich tut, ohne den Code zu durchsuchen.

Umgekehrtes Lama
quelle
Ich mag keine Kurzformen von Namen. Einerseits ist es sinnvoll, einen eindeutigen (ish) Namensstil zu haben, um alle Verwendungen zu finden. Andererseits, und vielleicht hatte ich Glück, musste ich keine Schlösser finden. Ich stelle mir vor, wenn ich nach "lock" suchen müsste ("lock" würde mir ein ausreichend gutes Ergebnis mit wenigen Fehlalarmen liefern, die ich leicht ignorieren könnte.
Chris Sinclair,