繁体   English   中英

试图理解可重入锁条件

[英]Trying to understand the Reentrant lock condition

I was reading @Ashish Lahoti coment in this post: https://stackoverflow.com/a/64077645/15456334 and in "codingnconcepts" web page, I was traying to get a consistent output like:

ping 1
pong 1
ping 2
pong 2
.
.
.
ping 500
pong 500

总是“ping”然后“pong”不可能得到两个相同的词 ping ping 或 pong pong。

但是,如果我将时间重复次数更改为 500 并更改“conditionMet.await(2, TimeUnit.SECONDS);”中的时间到 0 "conditionMet.await(0, TimeUnit.SECONDS):" 我得到下一个 output:

ping 1
pong 1
ping 2
pong 2
.
.
.
Ping 493
Ping 494
Ping 495
Ping 496
Ping 497
Ping 498
Ping 499
Ping 500

正如您在 output 中看到的那样,存在 ping ping 重复。

我使用等待和通知方法并且输出总是可以的,我有预期的 output:

package pingponghilos;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Principal {

    public static void main(String[] args) {

        Runnable ping = new PingPong("PING");
        Runnable pong = new PingPong("pong");

        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.submit(ping);
        executorService.submit(pong);
        
        System.out.println("hola desde el main");
    }
    
}

class PingPong implements Runnable {

    private static final Object locker = new Object(); // Locker util
    private String name;

    public PingPong(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (locker) {
                System.out.println(name);
                locker.notifyAll();
                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

但我试图理解可重入锁定条件以实现与使用 wait() 和 notify() 相同的情况。

有什么建议么? 提前致谢。

我这样做了:

package pack_20;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class PingPongTest {

    // Objeto usado para el bloqueo
    public static final ReentrantLock locker = new ReentrantLock(true);

    public static void main(String[] args) {

        Condition c = locker.newCondition();
        PingPong ping = new PingPong("PING", c);
        PingPong pong = new PingPong("pong", c);

        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> futurePing = executorService.submit(ping);
        Future<Integer> futurePong = executorService.submit(pong);

        System.out.println("Fin del main");
    }

}

class PingPong implements Callable<Integer> {

    private int counter = 0;
    private final String name;
    private final Condition condition; // Condition usada para la instancia de ReentrantLock

    private static AtomicBoolean canSayPing = new AtomicBoolean();

    public PingPong(String name, Condition condition) {
        this.name = name;
        this.condition = condition;
    }

    @Override
    public Integer call() throws Exception {
        for (int i = 1; i <= 500; i++) {
            if (name.equalsIgnoreCase("ping")) {
                sayPing();
            } else {
                sayPong();
            }
            ++counter;
        }
        return counter;
    }

    public void sayPing() throws InterruptedException {

        PingPongTest.locker.lock();

        try {
            while (!canSayPing.get()) {
                condition.await(0, TimeUnit.SECONDS);
            }
            System.out.println(name);
            canSayPing.set(false);
            condition.signal();
        } finally {
            PingPongTest.locker.unlock();
        }

    }

    public void sayPong() throws InterruptedException {

        PingPongTest.locker.lock();

        try {
            while (canSayPing.get()) {
                condition.await(0, TimeUnit.SECONDS);
            }
            System.out.println(name);
            canSayPing.set(true);
            condition.signal();
        } finally {
            PingPongTest.locker.unlock();
        }
    }

}

Output:一直是我所期望的。

PING
pong
PING
pong
PING
pong
PING
pong
PING
.
.
.
PING
pong
PING
pong
PING
pong
PING
pong
PING

但我认为这不是一个好的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM