9 Stimmen

Verschachtelte Sperre für dasselbe Objekt Leistung

Kostet es Leistung, verschachtelte Sperren für dasselbe Objekt zu verwenden?

Sagen wir, wir haben:

    public void AddRange(IEnumeratable<Item> items)
    {
        lock (_syncObject)
        {
            foreach (Item item in items)
            {
                InsertItem(item);
            }
        }
    }

    public void InsertItem(Item item)
    {
        lock (_syncObject)
        {
            //..
        }
    }

Ist es in Ordnung, dies auf der "Leistungsseite" zu tun?

Vielen Dank im Voraus.

7voto

Andrew Bezzub Punkte 15286

Lock hat Kosten, ich schlage Ihnen vor, Ihren Code so zu implementieren:

public void AddRange(IEnumeratable<Item> items)
{
    lock (_syncObject) // Locking only once.
    {
        foreach (Item item in items)
        {
            InsertItemImpl(item);
        }
    }
}

private void InsertItemImpl(Item item)
{
     // inserting the item
}

public void InsertItem(Item item)
{
    lock (_syncObject)
    {
        InsertItemImpl(item);
    }
}

2voto

Pasi Savolainen Punkte 2360

lock ist nicht kostenlos. es hat vor der Rückkehr auf bestimmte Dinge zu achten. Wie viele Dinge und was sie zu tun hat, hängt von der Implementierung ab. Ich würde deviner dass diese Art der Nutzung üblich ist und MS einige Optimierungen für diesen Anwendungsfall vorgenommen hat.

Ich würde immer noch empfehlen, dass Sie eine separate Implementierung von AddRange mit all den Dingen in einem Schuss getan haben. Das hängt natürlich vom Rest der Schnittstelle der Klasse ab (gibt es Listener und können sie Nachrichten empfangen, dass mehrere Objekte hinzugefügt wurden usw.).

Dies ist ziemlich einfach Testfall, tun einige Millionen von verschachtelten Sperren (was Sie vorschlagen) und das gleiche mit einer anderen Sperre.

Beachten Sie auch die unterschiedliche Reihenfolge, die möglich ist, wenn Sie eine nicht verschachtelte Sperre verwenden; Sie können ein Objekt in der Mitte eines Bereichs erhalten, den Sie hinzufügen:

AddRange _sync1
  AddItem _sync2
  AddItem _sync2
  --- interruption, other thread calls:
  AddItem _sync2
  --- AddRange again:
  AddItem _sync2

Bei der Synchronisierung mit einem einzelnen _syncObject kann niemand unterbrechen, da die Sperre bereits von einem anderen Thread gehalten wird.

1voto

Bastiaan Linders Punkte 1586

Ich weiß nicht, wie sich das auf die Leistung auswirkt, aber wenn wir erwarten, dass es die Leistung verringert, würde ich vorschlagen, dass Sie Ihren Code andersherum implementieren:

public void InsertItem(Item item)
{
    AddRange(new IEnumeratable({item}))
}

public void AddRange(IEnumeratable<Item> items)
{
    lock (_syncObject)
    {
        foreach (Item item in items)
        {
            // Insert code ..
        }
    }
}

@AddRange(new IEnumeratable({item})) : Ich bin kein Syntax-Kenner, also korrigieren Sie mich bitte, wenn das nicht richtig ist!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X