Es sieht für mich wie Sie Ihr Problem überdenken sollte.
Häufig verwenden Sie Pools von etwas (Gewinde, Anschlüsse, was auch immer) und wann immer ein etwas benötigt wird, ein Aufruf zum Pool-Provider-Objekt gibt einen Verweis auf das gewünschte Objekt aus. Bis dieses Objekt an den Pool zurückgegeben wird (durch Aufrufen der Entsperrungsmethode), ist keine weitere Sperrung erforderlich, da die gesamte Idee darin besteht, dass das Objekt jetzt ausschließlich dem Thread gehört, der es aus dem Pool angefordert hat (und der Pool nicht angibt) das Objekt erneut auslesen, bevor es vom Eigentümer Thread zurückgegeben wurde).
In diesem Muster wird normalerweise eine einzelne Sperre (für den Pool) implementiert, die einfach durch Synchronisierung des Poolobjekts (oder eines dedizierten Sperrobjekts) implementiert wird. Die einzigen Methoden, die Sperren und Entsperren durchführen, befinden sich alle im Pool (require() und release()). Die verwalteten Objekte selbst enthalten keine Sperren.
In der einfachsten Versionen es könnte wie folgt aussehen:
class MyResource {
// represents the managed resources
}
class MyPool {
private List<MyResource> available = new ArrayList<>();
public synchronized MyResource obtain() {
MyResource result = available.isEmpty()
? new MyResource() : available.remove(0);
return result;
}
public synchronized void release(MyResource resource) {
available.add(resource);
}
}
Offensichtlich ich den gesamten Code Verwendung weggelassen den Pool, um tatsächlich zu initialisieren und Sie können den Fall behandeln wollen, dass keine Ressource dort verfügbar ist anders (zB indem man wartet, bis man verfügbar ist, anstatt ein neues zu erstellen).
Eine Variante davon ist, dass die Ressourcenklasse einen Verweis auf ihren Pool hat und die release() -Methode auf die Ressourcenklasse verschiebt; Das wiederum ruft eine nichtöffentliche Methode im Pool auf, um die eigentliche Veröffentlichung durchzuführen.
Mit ein wenig Planungsaufwand können Lock-Free-Versionen dieses Musters mit der compareAndSet() - Methode von AtomicReference implementiert werden, um den Poolinhalt zu verwalten, ohne irgendwo synchronisiert zu werden.
Auch wenn Java das erlaubt, geht es gegen das Prinzip einer Sperre. Eine Sperre soll von einem Thread gehalten werden, der Dinge an ihr Objekt anlegt, und wenn das erledigt ist, gibt das Objekt das Objekt frei, damit andere Threads dasselbe tun – Jeeter