Domanda

Che cosa sta facendo l'implementazione di ReenTantlock#Trylock (Long, TimeUnit) quando cerca di far scattare una serratura? Supponiamo che il thread sia proprietario del blocco di myLock, e thread b call myLock.tryLock(10,SECONDS), il filo B sta dormendo o sta aspettando?

In altre parole, è stata la differenza di queste 2 implementazioni:

1.

while (true)
   try {
     if (readLock.tryLock())
       return;
     MILLISECONDS.sleep(5);
   }catch (InterruptedException e) {}

2.

 while (true)
   try {
     if (readLock.tryLock(5,MILLISECONDS))
       return;
   }catch (InterruptedException e) {}
È stato utile?

Soluzione

Prima di tutto, il secondo aspetterà meno di 5 millis se Lock rilasciato, perché non ha bisogno di aspettare svegliarsi dal sleep. Quindi, è meno esposto al problema della fame.

Quindi, j.u.c.l Il pacchetto utilizza i metodi LockSupport#Park per mettere in pausa un thread, non Thread.sleep. E a quanto ho capito fa la differenza sullo scheduler di thread, il park consente una latenza inferiore, ma non sono sicuro di come esattamente il sleep è implementato.

Inoltre, il tuo codice non ha alcun senso, esattamente lo stesso effetto potrebbe essere raggiunto da lock() metodo.

Altri suggerimenti

Sta aspettando il blocco e il thread è addormentato.

Internamente, se il tryLock(long, TimeUnit) Il metodo non riesce ad acquisire immediatamente il blocco, attende la quantità di tempo specificata. Se il blocco diventa disponibile prima di questo periodo di tempo, ritorna immediatamente con il blocco. Si noti che in questo caso, quando ci sono più thread che richiedono un blocco, il ReentrantLock Sceglierà casualmente un thread per dare il blocco al prossimo. Questo comportamento può essere cambiato passando true al valore di equità nel costruttore new ReentrantLock(true).

Il secondo esempio verificherà solo il blocco ogni cinque millisecondi. Se il blocco diventa disponibile mentre dorme e viene dato a un altro thread prima che si svegli, questo thread non sarà disponibile per l'acquisizione del blocco.

Se stai utilizzando questo codice con molti thread in attesa del blocco, nota che nessuna soluzione che hai fornito garantirà che ogni thread otterrà il blocco ad un certo punto. Il secondo codice può continuare a farsi tagliare da un altro thread poco prima che i cinque millisecondi siano aumentati. Il primo codice è casuale, ma anche con il valore di equità set ogni thread rinuncerà al suo posto in linea ogni cinque millisecondi. In questo caso, è meglio aumentare il valore del timeout. Un buon valore sarebbe circa il doppio del tempo massimo che ti aspetteresti che ci vuole affinché ogni thread ottenga un turno.

Tecnicamente non c'è differenza rispetto allo stato del thread in attesa. Dal Javadoc:

Se il blocco è trattenuto da un altro thread, il thread corrente diventa disabilitato per scopi di pianificazione del thread e si dà dormiente [...

Questo è molto simile a ciò che accade in caso di sonno, ma immagino che non possiamo dire con certezza se non conosciamo l'implementazione.

Ora, nota questa parte:

...] giace dormiente fino a quando non si verifica una delle tre cose: il blocco viene acquisito dal thread corrente; o [...

Ciò significa che nel caso in cui il blocco diventi libero nel frattempo lo acquisirà e tornerà. Nell'altro caso, mentre dorme, il filo non ha alcuna possibilità di ottenere il blocco anche se è gratuito.

Un'altra sottile differenza che può apparire tra i due casi è il fatto che il trylock a tempo è sensibile alla politica di equità del rientrante. Questo è:

Se questo blocco è stato impostato per utilizzare un criterio di ordinazione equo, non verrà acquisito un blocco disponibile se altri thread sono in attesa del blocco.

È noto che il triplock non eliminato non sia giusto e potrebbe riuscire ad acquisire il blocco anche se altri thread lo stanno già aspettando.

Immagino che il secondo aspetterà che un 5 millisecondi abbia una differenza con il primo che proverà a bloccarsi immediatamente. Quindi il thread B aspetterà se in 5 ms (entro 5 ms) non ottiene un blocco, tornerà falso. Normalmente non c'è differenza se hai 5ms nel tuo timeout, ma nel caso in cui si verifichi questo numero otterrai l'immagine chiara.

5ms è un timeout, aspetterà 5ms per un blocco che significa se il blocco è disponibile dopo 3ms tornerà dopo 3 ms con vero.

Per un ottimo riferimento su come vengono implementate le serrature e le altre primitive di concorrenza, vedi Eccellente di Shavit e Herlihy L'arte della programmazione multiprocessore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top