¿por qué parece que dos hilos están accediendo a una cerradura en mi código?

James :

Estoy tratando de aprender java multithreading, y este es un problema de concurrencia sencilla leetcode ( https://leetcode.com/problems/print-foobar-alternately/ ). Se me ocurrió el siguiente código, pero no entiendo por qué funciona. El problema, dice una llamada foo hilo y un hilo de restricción de llamadas, y debe imprimir "foobar" n veces.

public class Foobar {
    int n;
    boolean hasFoo;
    Lock lock;
    Condition cond;
    public Foobar(int n) {
        this.n = n;
        hasFoo = false;
        lock = new ReentrantLock();
        cond = lock.newCondition();
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            while (hasFoo) {
                cond.await();
            }
            printFoo.run();
            hasFoo = true;
            cond.signalAll();
            lock.unlock();
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            while (!hasFoo) {
                cond.await();
            }
            printBar.run();
            hasFoo = false;
            cond.signalAll();
            lock.unlock();
        }
    }
}

Funciona, pero no entiendo por qué. Desde mi entender, si la "barra" hilo se ejecuta primero y adquiere el bloqueo, se debe esperar y el hilo "foo" bloqueará en la lock.lock();línea, pero resulta que ambos entran en la parte cerrada. Por favor ilumíneme donde me entiendan mal encierro en Java. Así es como yo llamo a estos dos métodos.

        Foobar f = new Foobar(10);
        Runnable rf = () -> {
            try {
                f.foo(() -> System.out.println("foo"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        };
        Runnable rp = () -> {
            try {
                f.bar(() -> System.out.println("bar"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        };
        Thread t1 = new Thread(rf, "foo-thread");
        Thread t2 = new Thread(rp, "bar-thread");
        t1.start();
        t2.start();
Andrew Tobilko:

Si la "barra" hilo se ejecuta primero y adquiere el bloqueo, debe esperar ...

¿Esperar para que? La "barra" hilo es el primero que adquirió la cerradura, no hay nada que esperar. Este hilo se procederá inmediatamente a la siguiente instrucción, que es cond.await();donde el bloqueo se libera 1 , y el hilo se irá a dormir.

Mientras tanto, el hilo "foo" puede adquirir el bloqueo 2 , e imprimir su mensaje, y notificar a otros que su trabajo está hecho, que, posteriormente, se desbloquea 3 el dormir "barra".

... el hilo "foo" será bloqueada en el lock.lock();

Exactamente.

pero resulta que ambos entran en la parte cerrada.

No. Se entraba, otro está a la espera para entrar. Es una cerradura sencilla - sólo un hilo puede adquirir a la vez (que es como una versión avanzada de la synchronizeddeclaración).


1 El bloqueo asociado con esta condición es atómicamente liberado y el hilo actual se desactiva con fines de planificación de hebras y permanece latente

https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/concurrent/locks/Condition.html#await ()

2 Recuerde, fue bloqueada ya que trató de adquirir el traje corto de bloqueo después de la "barra" lo hizo.

Si el bloqueo no está disponible, el subproceso actual se incapacita para fines de programación hilo y permanece latente hasta que el bloqueo ha sido adquirido.

https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/concurrent/locks/Lock.html#lock ()

3 Por señalización a todos, que uno de los cuatro métodos a otros despierto.

  1. Algunos otro hilo invoca el signalAll()método para esto Condition;

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#await ()

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=233286&siteId=1
Recomendado
Clasificación