nel cercare di migliorare la mia comprensione su problemi di concorrenza, sto guardando il seguente scenario (Edit: ho cambiato l'esempio dall'elenco a runtime, che è più vicino a quello che sto cercando):Determinazione dell'ambito di sincronizzazione?
public class Example {
private final Object lock = new Object();
private final Runtime runtime = Runtime.getRuntime();
public void add(Object o) {
synchronized (lock) { runtime.exec(program + " -add "+o); }
}
public Object[] getAll() {
synchronized (lock) { return runtime.exec(program + " -list "); }
}
public void remove(Object o) {
synchronized (lock) { runtime.exec(program + " -remove "+o); }
}
}
Allo stato attuale, ogni metodo è protetto da thread se usato standalone. Ora, quello che sto cercando di capire è come gestire dove la classe chiamata desidera chiamare:
for (Object o : example.getAll()) {
// problems if multiple threads perform this operation concurrently
example.remove(b);
}
Ma, come detto, non v'è alcuna garanzia che lo Stato sarà coerente tra la chiamata a getAll() e le chiamate a rimuovere(). Se più thread chiamano questo, sarò nei guai. Quindi la mia domanda è - Come dovrei abilitare lo sviluppatore a eseguire l'operazione in modo thread-safe? Idealmente, desidero rafforzare la sicurezza del thread in un modo che rende difficile per lo sviluppatore evitare/perdere, ma allo stesso tempo non complicato da raggiungere. Posso pensare a tre opzioni finora:
A: attiva il blocco 'this', quindi l'oggetto di sincronizzazione è accessibile al codice chiamante, che può quindi racchiudere i blocchi di codice. Svantaggio: Difficile da rispettare in fase di compilazione:
synchronized (example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
B: Inserire il codice di combinati in classe Esempio - e beneficiare di essere in grado di ottimizzare l'attuazione, come in questo caso. Svantaggio: dolore per aggiungere estensioni e potenziale combinazione di logica non correlata:
public class Example {
...
public void removeAll() {
synchronized (lock) { Runtime.exec(program + " -clear"); }
}
}
C: Fornire una classe di chiusura. Svantaggio: il codice in eccesso, potenzialmente troppo generoso di un blocco di sincronizzazione, potrebbe infatti rendere più facile deadlock:
public interface ExampleClosure {
public void execute(Example example);
}
public Class Example {
...
public void execute(ExampleClosure closure) {
synchronized (this) { closure.execute(this); }
}
}
example.execute(new ExampleClosure() {
public void execute(Example example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
}
);
C'è qualcosa che mi manca? Come dovrebbe essere la sincronizzazione per garantire che il codice sia thread-safe?
Siamo spiacenti, l'esempio è stato un po 'incerto. Ho rimosso il riferimento a Elenco. Sto solo cercando di capire il modo migliore per affrontare: Blah result = example.method1(); example.method2 (risultato); dove la chiamata a method2 può causare problemi perché tra il metodo1 e il metodo2, un altro thread è andato e chiamato method3(). – Mike