Domanda

Il semaforo può essere inferiore a 0? Voglio dire, suppongo di avere un semaforo con N = 3 e chiamo " down " 4 volte, quindi N rimarrà 0 ma un processo verrà bloccato?

E allo stesso modo, se all'inizio chiamo, N può essere superiore a 3? Perché come la vedo io, se N può essere maggiore di 3 se all'inizio chiamo un paio di volte, poi in seguito potrei richiamare più volte di quanto posso, mettendo così più processi nella sezione critica quindi il semaforo mi permette .

Se qualcuno lo chiarisse un po 'per me lo apprezzerei molto.

Greg

È stato utile?

Soluzione

Richiamare quando è 0 non dovrebbe funzionare. Richiamare quando è 3 funziona. (Sto pensando a Java).

Lasciami aggiungere un po 'di più. Molte persone pensano a blocchi come semafori (binari) (cioè - N = 1, quindi il valore del semaforo è 0 (trattenuto) o 1 (non trattenuto)). Ma questo non è del tutto giusto. Un lucchetto ha la nozione di "proprietà". quindi potrebbe essere "rientrante". Ciò significa che a un thread che contiene un blocco è consentito richiamare nuovamente lock () (spostando effettivamente il conteggio da 0 a -1), poiché il thread contiene già il blocco ed è autorizzato a "rientrare". esso. Le serrature possono anche essere non rientranti. Un detentore di un blocco dovrebbe chiamare lo sblocco () lo stesso numero di volte di blocco ().

I semafori non hanno nozione di proprietà, quindi non possono rientrare, anche se è possibile acquisire tutti i permessi disponibili. Ciò significa che un thread deve essere bloccato quando incontra un valore pari a 0, finché qualcuno non incrementa il semaforo.

Inoltre, in quello che ho visto (che è Java), puoi incrementare il semaforo maggiore di N, e anche questo ha a che fare con la proprietà: un semaforo non ha nozione di proprietà, quindi chiunque può dargli più permessi . A differenza di un thread, dove ogni volta che un thread chiama unlock () senza tenere un blocco, questo è un errore. (In Java genererà un'eccezione).

Spero che questo modo di pensarci sia d'aiuto.

Altri suggerimenti

(Utilizzando la terminologia di java.util.concurrent.Semaphore dato il tag Java. Alcuni di questi dettagli sono specifici dell'implementazione. Sospetto che il tuo " down " sia il acquisito () del semaforo Java e il tuo metodo "quot & up" è release () .)

Sì, l'ultima chiamata a acquisisci () si bloccherà fino a quando un altro thread chiama release () o il tuo thread viene interrotto.

Sì, puoi chiamare release () più volte, quindi giù più volte - almeno con java.util.concurrent.Semaphore .

Alcune altre implementazioni di un semaforo potrebbero avere un'idea di un "massimo" numero di permessi, e una chiamata a rilasciare oltre quel massimo fallirebbe. La classe Java Semaphore consente una situazione inversa, in cui un semaforo può iniziare con un numero negativo di permessi e tutte le chiamate acquisisci () falliranno fino a quando non ci saranno abbastanza < code> release () chiamate. Una volta che il numero di permessi è diventato non negativo, non diventerà mai più negativo.

Ciao Greg, considera il seguente esempio:

public static void main(String [] args) throws InterruptedException {

        Semaphore available = new Semaphore(1, true);

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());
    }

Se vedi l'output otterrai:

Acquire : 0
Released : 1
Released : 2
Released : 3
Released : 4
Acquire : 3
Acquire : 2
Acquire : 1
Acquire : 0

E l'attesa sta succedendo.

Quindi, in sostanza, il permesso aumenterà ad ogni rilascio e l'acquisizione lo diminuirà fino a 0. Una volta raggiunto 0, attenderà fino a quando non viene chiamato il rilascio sullo stesso oggetto :)

Sì, un valore negativo indica che hai processi in attesa del rilascio del semaforo. Un valore positivo significa che puoi chiamare acquisisci molte volte prima dei blocchi semaforo.

Potresti pensare al valore in questo modo: un numero positivo significa che ci sono molte risorse disponibili. Un valore negativo significa che ci sono molte entità che necessitano di una risorsa quando tutte le risorse sono prese al momento. Quando acquisisci una risorsa diminuisci il valore, quando lo rilasci aumenti il ??valore. Se il valore è ancora > = 0 dopo il decremento ottieni la risorsa, altrimenti la tua entità viene messa in coda.

Una bella spiegazione dei semafori in Wikipedia: http://en.wikipedia.org/wiki/Semaphore_(programming)

Basta vedere N come contatore che conta la tua risorsa limitata. Dato che non puoi avere un numero negativo di risorse, N rimane > = 0. Se il numero delle tue risorse disponibili cambia, anche la N massima deve essere cambiata. Non lo considero un buon stile per incrementare n senza prima decrementarlo in nessun altro caso.

Utilizzando java.util.concurrent.Semaphore con i metodi acquisisci () e release () , penso che i permessi saranno sempre > = 0 . Diciamo che vuoi sincronizzare i thread in modo che solo 1 thread possa essere dentro per il loop. Se sem è il tipo di Semaphore con valore iniziale 1, questo non funzionerà per più di 2 thread.

while(true){            

    sem.wait(); // wait is acquire

    for(int i=0; i<=5; i++){

        try {
            Thread.sleep(250);
        }catch (InterruptedException e) {}

        System.out.println("Thread "+ threadname+ " " + i);

             }
    sem.signal(); // signal is release }

Tuttavia, puoi implementare la classe Semaphore da Java e creare la tua classe che lo consenta.

package yourpackage;

import java.util.concurrent.Semaphore;

public class SemaphoreLayer {
public Semaphore s=null;
public String name;
private int val;

public SemaphoreLayer(int i){
    s=new Semaphore(i); val=i;
}

public void wait(){
 try {
     val--;
     s.acquire();

  } catch (InterruptedException e) {
    System.out.println("Error signal semaphorelayer");
}}

public void signal(){
    if(val<0){val++;}{
        s.release();
        val++;
    }
}

}

Ora val può essere negativo. Tuttavia, non sono sicuro che sia completamente sicuro, perché se abbiamo segnale da un thread e aspettiamo dall'altro e provano val ++ e val-- questo può essere male. (le possibilità sono molto piccole ma esistono ancora, quindi se stai programmando e devi essere al 100% senza errori, non ti consiglio di usare questo codice) In conclusione, è per questo che è meglio usare il concetto di monitor in java e la parola chiave sincronizzata.

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