Ordine di bloccaggio di gregge?
Domanda
Sto usando un semplice script di prova dahttp://www.tuxradar.com/practicalphp/8/11/0come questo
<?php
$fp = fopen("foo.txt", "w");
if (flock($fp, LOCK_EX)) {
print "Got lock!\n";
sleep(10);
flock($fp, LOCK_UN);
}
Ho aperto 5 shell ed eseguito lo script uno dopo l'altro il blocco degli script fino a quando il blocco non è stato libero e poi continua dopo il rilascio
Non sono davvero interaficato in cose PHP, ma la mia domanda è: qualcuno conosce l'ordine in cui viene acquisito il gregge ()?
e.g.
t0: process 1 lock's
t1: process 2 try_lock < blocking
t2: process 3 try_lock < blocking
t3: process 1 releases lock
t4: ?? which process get's the lock?
Esiste un semplice ordine deterministico, come una coda o il kernel "solo" sceglie uno per "regole più avanzate"?
Soluzione
Se ci sono più processi in attesa di un blocco esclusivo, non è specificato quale sia riuscito ad acquisirlo per primo. Non fare affidamento su nessun ordine particolare.
Detto questo, l'attuale codice del kernel li sveglia nell'ordine che hanno bloccato. Questo commento è in fs/locks.c
:
/* Insert waiter into blocker's block list.
* We use a circular list so that processes can be easily woken up in
* the order they blocked. The documentation doesn't require this but
* it seems like the reasonable thing to do.
*/
Se si desidera eseguire una serie di processi in ordine, non utilizzare flock()
. Usa i semafori SYSV (semget()
/ semop()
).
Crea un set di semaforo che contiene un semaforo per ciascun processo dopo il primo e iniziali tutti a -1. Per ogni processo dopo il primo, fai a semop()
sul semaforo di quel processo con a sem_op
Valore di zero: questo lo bloccerà. Dopo il completamento del primo processo, dovrebbe fare a semop()
sul semaforo del secondo processo con a sem_op
Valore di 1 - Questo sveglierà il secondo processo. Dopo il completamento del secondo processo, dovrebbe fare a semop()
sul semaforo del terzo processo con a sem_op
valore di 1 e così via.