2009-12-05 15 views
8

Ho due array e devo sincronizzare l'accesso ad essi attraverso i thread. Li inserirò in un blocco sincronizzato. Il problema è che posso passare solo uno di loro a "sincronizzati" con una sola operazione.blocco sincronizzato java per più di 1 oggetti?

Come si assicura che l'accesso ad entrambi gli array sia sincronizzato? Li inserisco in una classe e ne creo un oggetto? Oppure accedo all'altro array solo nel blocco sincronizzato e questo si occupa dell'accesso sincronizzato ad esso?

Grazie,

+0

Inserirli in una nuova classe può aiutare a chiarire cosa si vuole fare, quindi lo consiglierei. Tuttavia, ciò non influisce affatto sulla sicurezza del thread. Mi piace la risposta che utilizza i blocchi espliciti (sotto). –

risposta

20

Qualunque cosa tu faccia non fanno fare questo:

synchronized (array1) { 
    synchronized (array2) { 
    // do stuff 
    } 
} 

Questo rischia di portare a deadlock meno che non siate molto attenti. Se fai questo approccio, devi assicurarti di avere un ordine parziale invariato sugli oggetti - Google "Dining Philosophers" per discutere delle insidie.

Fondamentalmente quello che dovete fare è creare un oggetto di blocco che si intende utilizzare, se si desidera accedere sia array e quindi utilizzare tale per tutti gli accessi array. È a grana grossa ma sicura. Si potrebbe fare in questo modo:

public static class TwoArrays { 
    private int[] array1 = ... 
    private int[] array2 = ... 
    private final Object LOCK = new Object(); 

    public void doUpdate() { 
    synchronized (LOCK) { 
     ... 
    } 
    } 
} 

Se avete bisogno di un metodo più dettagliato che si desidera utilizzare il Java 5+ simultanei utility come ReadWriteLock ma questo sarà più complicato da implementare e soggetto a errori.

+1

Si potrebbe anche fare "doUpdate" sincronizzato, quindi, piuttosto che avere la complessità aggiuntiva dell'oggetto 'LOCK'. – skaffman

+3

In realtà no, è consigliabile non esporre i blocchi, che è ciò che si sta facendo quando si utilizza questo come un blocco. – cletus

+0

questo fa sorgere una domanda: l'utilizzo del blocco sincronizzato nidificato può portare a un deadlock, nel caso in cui ci sia un'altra sincronizzazione sugli stessi oggetti. Ma succederà quando sarà presente solo il codice sopra? Nessun thread può acquisire il monitor di array2 se non ha già il monitor di array1. E se ha il monitor di array1, nessun altro thread può avere il monitor di array2. Ho un buco nel mio ragionamento? – Bozho

11

cose Prima di Java 5, avrei scritto così:

// pre Java 5 code: 
Object lock = new Object(); 
// ... 
synchronized(lock) { 
    // do something that requires synchronized access 
} 

Ma dal momento che Java 5, mi piacerebbe utilizzare le classi da java.util.concurrent.locks (personalmente, non trovo questo più complicato o un errore -prone):

// Java 5 Code Using Locks 
Lock lock = // ... 
lock.lock(); 
try { 
    // do something that requires synchronized access 
} 
finally { 
    lock.unlock(); 
} 

Se avete bisogno di lettura-scrittura di chiusura, ecco ad esempio implementato utilizzando blocchi di lettura e scrittura da Java 5:

private ReadWriteLock rwl = new ReentrantReadWriteLock(); 
private Lock rLock = rwl.readLock(); 
private Lock wLock = rwl.writeLock(); 

private List<String> data = new ArrayList<String>(); 

public String getData(int index) { 
    rLock.lock(); 
    try { 
     return data.get(index); 
    } finally { 
     rLock.unlock(); 
    } 
} 

public void addData(int index, String element) { 
    wLock.lock(); 
    try { 
     data.add(index, element); 
    } finally { 
     wLock.unlock(); 
    } 
} 

Naturalmente, adattarlo alle proprie esigenze.

Problemi correlati