Pregunta

¿Puede el semáforo ser inferior a 0? Quiero decir, digamos que tengo un semáforo con N = 3 y llamo "abajo". 4 veces, ¿entonces N permanecerá 0 pero se bloqueará un proceso?

Y lo mismo a la inversa, si al principio llamo, ¿puede N ser mayor que 3? Porque, como lo veo, si N puede ser mayor que 3 si al principio llamo un par de veces, luego podría llamar más veces de lo que puedo, poniendo así más procesos en la sección crítica, entonces el semáforo me permite .

Si alguien me aclarara un poco, lo agradecería mucho.

Greg

¿Fue útil?

Solución

Llamar cuando es 0 no debería funcionar. Llamar cuando son las 3 sí funciona. (Estoy pensando en Java).

Déjame agregar un poco más. Muchas personas piensan en bloqueos como semáforos (binarios) (es decir, N = 1, por lo que el valor del semáforo es 0 (retenido) o 1 (no retenido)). Pero esto no está del todo bien. Una cerradura tiene una noción de `` propiedad '' entonces puede ser "reentrante". Eso significa que un subproceso que mantiene un bloqueo puede volver a llamar a lock () (mover efectivamente el conteo de 0 a -1), porque el subproceso ya mantiene el bloqueo y se le permite volver a ingresar. eso. Las cerraduras también pueden no ser reentrantes. Se espera que un titular de bloqueo llame a desbloqueo () la misma cantidad de veces que lock ().

Los semáforos no tienen noción de propiedad, por lo que no pueden ser reentrantes, aunque se pueden adquirir tantos permisos como estén disponibles. Eso significa que un hilo necesita bloquearse cuando encuentra un valor de 0, hasta que alguien incremente el semáforo.

Además, en lo que he visto (que es Java), puede incrementar el semáforo mayor que N, y eso también tiene que ver con la propiedad: un semáforo no tiene noción de propiedad, por lo que cualquiera puede darle más permisos . A diferencia de un hilo, donde cada vez que un hilo llama a unlock () sin mantener un bloqueo, eso es un error. (En Java arrojará una excepción).

Espero que esta forma de pensar sea útil.

Otros consejos

(Usando la terminología de java.util.concurrent.Semaphore dada la etiqueta Java. Algunos de estos detalles son específicos de la implementación. Sospecho que su " down " es el adquirir () del semáforo de Java método, y su " arriba " es release () .)

Sí, su última llamada a adquirir () se bloqueará hasta que otro hilo llame a release () o su hilo se interrumpa.

Sí, puede llamar a release () más veces, luego bajar más veces, al menos con java.util.concurrent.Semaphore .

Algunas otras implementaciones de un semáforo pueden tener una idea de un "máximo" número de permisos, y una llamada para liberar más allá de ese máximo fallaría. La clase Java Semaphore permite una situación inversa, donde un semáforo puede comenzar con un número negativo de permisos, y todas las llamadas adquirir () fallarán hasta que haya habido suficiente < llamadas code> release () . Una vez que el número de permisos se haya vuelto no negativo, nunca volverá a ser negativo.

Hola Greg, considera el siguiente ejemplo:

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());
    }

Si ve el resultado, obtendrá lo siguiente:

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

Y la espera continúa.

Entonces, básicamente, el permiso aumentará en cada lanzamiento y la adquisición lo disminuirá hasta 0. Una vez que llegó a 0, esperará hasta que se llame la liberación en el mismo objeto :)

Sí, un valor negativo significa que tiene procesos esperando que se libere el semáforo. Un valor positivo significa que puede llamar a adquirirlo muchas veces antes de que se bloquee el semáforo.

Podría pensar en el valor de esta manera: un número positivo significa que hay muchos recursos disponibles. Un valor negativo significa que hay muchas entidades que necesitan un recurso cuando se toman todos los recursos en este momento. Cuando adquiere un recurso, disminuye el valor, cuando lo libera aumenta el valor. Si el valor sigue siendo > = 0 después de la disminución, obtiene el recurso, de lo contrario, su entidad se pone en cola.

Una buena explicación de los semáforos en Wikipedia: http://en.wikipedia.org/wiki/Semaphore_(programming)

Simplemente vea N como el contador que cuenta su recurso limitado. Como no puede tener un número negativo de recursos, N permanece > = 0. Si el número de sus recursos disponibles cambia, también se debe cambiar el N máximo. No consideraría un buen estilo incrementar n sin disminuirlo primero en ningún otro caso.

Usando java.util.concurrent.Semaphore con los métodos adquirir () y release () , creo que los permisos siempre serán > = 0 . Digamos que desea sincronizar hilos para que solo 1 hilo pueda estar dentro para el bucle. Si sem es un tipo de Semaphore que tiene un valor inicial de 1, esto no funcionará para más de 2 hilos.

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 }

Sin embargo, puede implementar la clase Semaphore desde java y crear su propia clase que lo permita.

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++;
    }
}

}

Ahora val puede ser negativo. Sin embargo, no estoy seguro de que esto sea completamente seguro, porque si tenemos señal de un hilo y esperamos del otro e intentan val ++ y val-- esto puede ser malo. (las posibilidades de esto son muy pequeñas, pero aún existen, por lo que si está codificando y tiene que estar al 100% sin errores, no recomiendo usar este código) En conclusión, esta es la razón por la cual es mejor usar el concepto de monitores en Java y palabras clave sincronizadas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top