【问题标题】:Trying to understand the Reentrant lock condition试图理解可重入锁条件
【发布时间】:2021-04-07 15:16:38
【问题描述】:

我正在阅读这篇文章中的@Ashish Lahoti 评论:https://stackoverflow.com/a/64077645/15456334,并且在“codingnconcepts”网页中,我正在尝试获得一致的输出,例如:

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):" 我得到下一个输出:

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

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

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

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() 相同的条件。

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

【问题讨论】:

    标签: java concurrency


    【解决方案1】:

    我这样做了:

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

    输出:总是符合我的预期。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-18
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      相关资源
      最近更新 更多