2016-09-14 3 views
4

Betrachten Sie die folgende Methode:Java synchronisierte Methode um Parameterwert

public void upsert(int customerId, int somethingElse) { 
    // some code which is prone to race conditions  
} 

Ich mag diese Methode von Rennbedingungen schützen, aber dies kann nur auftreten, wenn zwei Threads mit den gleichen customerId sind es zugleich Aufruf . Wenn ich die ganze Methode mache synchronized wird es die Effizienz reduzieren und es ist nicht wirklich notwendig. Was ich wirklich will, ist es, es um die customerId zu synchronisieren. Ist das irgendwie mit Java möglich? Gibt es dafür eingebaute Tools oder würde ich eine Map von Integers als Sperren verwenden?

Auch fühlen sich frei zu beraten, wenn Sie denken, dass ich etwas falsch hier tun :)

Dank!

+1

Es sicherlich * fühlt sich falsch *. Vielleicht sollten Sie Ihre Frage bearbeiten, um mehr Details darüber zu erhalten, warum Sie überhaupt eine Synchronisierung benötigen. –

+3

upsert klingt, als würde es einige Datenbank dml ausführen. In diesem Fall versuchen Sie möglicherweise, ein Transaktionsisolationsproblem durch Sperren zu beheben? Wenn ja, wäre das eine schlechte Idee. –

+0

@NathanHughes Ich benutze eine alte Version von Postgres, wo Upsert noch nicht verfügbar ist :) –

Antwort

11

Das Konzept, das Sie suchen, heißt segmentierte Verriegelung oder gestreifte Verriegelung. Es ist zu verschwenderisch, ein separates Schloss für jeden Kunden zu haben (Schlösser sind ziemlich schwer). Stattdessen möchten Sie Partition Ihre Kundennummer Platz in einer angemessenen Anzahl von Partitionen, die Übereinstimmung mit dem gewünschten Grad der Parallelität. Normalerweise sind 8-16 ausreichend, aber dies hängt von der Menge der Arbeit ab, die die Methode macht.

Dies umreißt einen einfachen Ansatz:

private final Object[] locks = new Object[8]; 

synchronized (locks[customerId % locks.length]) { 
    ...implementation... 
} 
Verwandte Themen