2010-07-22 11 views

risposta

13

Se si sta parlando dell'utilizzo di un meccanismo di blocco (o anche di barriere di sincronizzazione) basta usare uno java.util.concurrent.Lock. L'ovvio suggerimento è di usare un ReentrantLock che delega a uno Synch. La sincronizzazione è un AQS che a sua volta utilizza LockSupport.

Tutto fatto sotto le coperte per voi.

Edit:

Non andiamo oltre gli usi pratici di AbstractQueuedSynchronizer (AQS).

Anche se i costrutti di concorrenza possono essere molto diversi nel loro utilizzo, tutti possono avere le stesse funzioni di base.

I.e. In alcune condizioni parcheggiare questo thread. Sotto altre condizioni, sveglia un thread.

Questo è un insieme molto ampio di istruzioni ma rende ovvio che la maggior parte delle strutture di concorrenza necessiterebbe di alcune funzionalità comuni che sarebbero in grado di gestire tali operazioni per esse. Inserisci AQS. Esistono cinque principali barriere di sincronizzazione.

  • ReentrantLock
  • ReadLock
  • WriteLock
  • Semaphore
  • CountDownLatch

Ora, tutti questi cinque strutture sono molto diverso insieme di regole quando li utilizzano. Un CountdownLatch può consentire l'esecuzione di molti thread contemporaneamente ma forza uno (o più) thread ad attendere fino a quando almeno un numero n di thread esegue il conto alla rovescia su detto latch.

ReentrantLock forza un solo thread alla volta per accedere a una sezione critica e accoda tutti gli altri thread per attendere il completamento.

ReadLock consente qualsiasi numero di thread di lettura nella sezione critica fino a quando non viene acquisito un blocco di scrittura.

Gli esempi possono andare avanti, ma il quadro generale qui è che tutti usano AQS. Questo perché sono in grado di utilizzare le funzioni primitive che AQS offre e implementa funzionalità più complesse su di esso. AQS ti consente di parcheggiare e parcheggiare i fili (se necessario interrompendoli) ma in modo tale da poter supportare molte funzioni complesse.

+0

W.: Ho visto LockSupport viene utilizzato in 'AbstractQueuedLongSynchronizer', cosa suggerisce si tratta di una sorta di classe API interna? Volevo solo vedere qualsiasi pezzo di codice illustrativo per questo ... – Max

+2

@Max LockSupport è una classe di utilità che chiunque può utilizzare. Non è necessariamente una classe interna. Unsafe.java è un buon esempio di classe interna. LockSupport è pubblico in modo che altri possano scrivere la propria versione di AQS –

+0

W.: Grazie John, so che è per l'estensione. La tua risposta mi ha fatto riformulare una domanda: in generale l'uso di "AbstractQueuedSynchronizer" mi sembra impreciso. – Max

1

non sono pensati per l'uso diretto nel codice cliente; altro per aiutare a costruire nuove classi concorrenti.

1

AQS è una classe meravigliosa per la creazione di primitive di concorrenza - ma è complessa e richiede un po 'di studio per usarlo correttamente. L'ho usato per alcune cose come lazy initialisation e un semplice veloce reusable latch.

Per quanto complessa, non penso che AQS sia particolarmente vago, ha javadoc eccellenti che descrivono come usarlo correttamente.

+0

Esattamente ciò che è AQS? – Pacerier

+0

java.util.concurrent.AbstractQueuedSynchronizer –

+0

in realtà: java.util.concurrent.locks.AbstractQueuedSynchronizer –

0

AFAIK, AbstractQueuedSynchronizer viene utilizzato per gestire le transizioni di stato. Il JDK lo usa per estendere Sync, una classe interna per java.util.concurrent.FutureTask. La classe Sync gestisce gli stati (READY, RUNNING, RAN, e CANCELED) di FutureTask e le transizioni tra di essi.

Ciò consente, come saprai, di FutureTask di bloccare su FutureTask.get() fino a quando non viene raggiunto lo stato RAN, ad esempio.

Problemi correlati