filo java codice sicuro + un metodo questione atomica
-
11-09-2019 - |
Domanda
ho una classe Manager che sta per essere accessibile da più thread allo stesso tempo, voglio sapere se ho fatto nel modo giusto?
anche Penso di aver bisogno di essere RemoveFoo atomica, ma non sono sicuro
public class Manager
{
private ConcurrentHashMap<String, Foo> foos;
//init in constructor
public RemoveFoo(String name)
{
Foo foo = foos.Get(name);
foo.RemoveAll();
foos.Remove(name);
}
public AddFoo(Foo foo)
{...}
}
public class Foo
{
private Map<String,Bar> bars;
//intialize it in constructor
//same for RemoveBar
public void AddBar(Bar bar)
{
synchronized(this)
{
bars.put(bar.id, bar);
}
}
public void RemoveAll()
{
synchronized(this)
{
//some before removall logic for each one
bars.remove(bar.id, bar);
}
}
}
public class Bar
{}
Soluzione
RemoveFoo
potrebbe essere problematico. Suggerisco di usare:
Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();
, invece. Questo fa in modo che la mappa non cambia tra get()
e remove()
.
In Foo
, è sufficiente per sincronizzare il bars
anziché l'intera istanza. Ma questa è solo un'ottimizzazione minore.
Altri suggerimenti
Non hai bisogno di metodi sincronizzati come si utilizza un ConcurrentHashMap, però essere consapevoli che Foo foo = foos.Get(name)
potrebbe tornare null come un altro thread potrebbe già aver rimosso la voce dalla mappa.
I membri possono essere dichiarati come Map<String, Foo> foos
, ma devono essere initialsed come foos = new ConcurrentHashMap<String, Foo>;
Dichiarare RemoveFoo(String)
come synchronized
:
public synchronized void RemoveFoo(String name) {
…
}
Inoltre, essere informati di quanto segue:
- nomi dei metodi dovrebbero essere minuscole, ad esempio,
removeFoo
invece diRemoveFoo
. Questo non è C #. :) - Ogni metodo ha bisogno di un tipo di ritorno:
public removeFoo()
non è una dichiarazione di metodo validi, ha bisogno di esserepublic void removeFoo()
.
Se si utilizza un ConcurrentHashMap in Foo come
private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();
forse si può fare a meno la sincronizzazione in Foo pure.
Non sono sicuro di che cosa avete intenzione di fare sul Foo e bar, ma sembra che un modello di deallocazione.
Se non si fa riferimento da altri, basta chiamare foos.Remove (nome); e lasciare che il motore GC gestire la deallocazione.