Non capisco bene controllare e impostare in concorrenza

1

Non capisco del tutto il controllo e impostazione del comportamento .. ecco un esempio:

    public static void main(String[] args) {

    List<String> list = Collections.synchronizedList(new ArrayList<>());

    String abc = "123";

    if (!list.contains(abc)) {
        list.add(abc);

        // ... some several lines of code

        list.remove(abc);

    }

}

Ciò che non capisco ...

Quindi capisco che contains e add dovrebbero essere in un blocco synchronized(list) ...

ma per quanto riguarda remove ?

in caso contrario, quindi se fosse:

if (list.contains(abc)) {
   list.add(abc);
   list.remove(abc);
}  

?

Comprendo che il codice non ha molto senso ma lo sto solo usando come esempio ... remove deve essere nel blocco synchronized qui?

    
posta ycomp 21.10.2015 - 04:55
fonte

2 risposte

2

Probabilmente dovresti leggere Concurrency Java in Practice di Brian Goetz e altri

    
risposta data 28.10.2015 - 08:27
fonte
1

Ogni volta che è possibile accedere a una raccolta da più thread senza il blocco a un livello superiore (ad esempio su una base per transazione, piuttosto che per operazione), è possibile che qualcosa vada storto. Non è possibile eseguire operazioni condizionalmente su alcuna proprietà della raccolta, poiché tale proprietà potrebbe cambiare tra test ed esecuzione. Non è possibile eseguire un'iterazione sulla raccolta, poiché potrebbe cambiare durante il processo di iterazione. Tutto ciò che puoi fare è aggiungere elementi ad esso. Pertanto, ogni volta che ti ritrovi a voler utilizzare una raccolta sincronizzata, fai un passo indietro: quello che stai facendo è probabilmente il modo sbagliato di risolvere il tuo problema.

La sincronizzazione deve essere a un livello superiore rispetto alla raccolta oppure è necessario utilizzare una raccolta che implementa la logica di livello superiore richiesta dall'applicazione, ad es. una coda.

Per il tuo esempio specifico, il potenziale problema è che un oggetto uguale all'elemento che si sta aggiungendo potrebbe essere aggiunto da un altro thread, causando l'operazione di aggiunta nel codice che si cita per fallire. L'operazione remove rimuoverà quindi l'elemento aggiunto dall'altro thread, il che probabilmente non è quello che desideri (il codice sembra avere l'intento di lasciare la raccolta invariata al termine, ma cambiando temporaneamente durante un'operazione).

Ogni volta che è possibile, è meglio evitare di condividere l'accesso a basso livello ai valori mutabili tra i thread, e problemi come questo sono la ragione principale per cui.

    
risposta data 21.10.2015 - 16:35
fonte

Leggi altre domande sui tag