await()和signal()在锁块中是如何工作的?

0qx6xfy6  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(319)

为了我自己的理解,我写了两个线程,每个线程输出一行。然而,我想让这两个线程,使他们打印一个接一个。比如说 t1 以及 t2 . 如果 t1 打印自己的消息,然后它必须等待其他线程打印自己的消息。现在我设法通过实验使它工作,但有一些事情我不明白。
这是我的密码:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Multithread {

    public static void main(String [] m) throws InterruptedException, ExecutionException {
        Lock lock = new ReentrantLock();
        Condition c1 = lock.newCondition();

        Runnable t1 = new Runnable() {

            @Override
            public void run() {
                for(int i : new int[] {1,2,3,4,5}) {
                    lock.lock();
                    try {
                        c1.signal();
                        System.out.println("In thread 1 - " + i);

                        try {
                            c1.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } finally {
                        c1.signal();
                        lock.unlock();
                    }
                }

            }
        };

        Callable<String> t2 = new Callable<String>() {

            @Override
            public String call() throws Exception {
                for(int i : new int[] {1,2,3,4,5}) {
                    lock.lock();
                    try {
                        c1.signal();
                        System.out.println("In callable 2 - " + i);
                        try {
                            c1.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } finally {
                        c1.signal();
                        lock.unlock();
                    }
                }

                return "This is callable";
            }

        };

        new Thread(t1, "t1").start();
        FutureTask<String> task = new FutureTask<>(t2);
        new Thread(task, "t2").start();
        //c1.signalAll();
        System.out.println(task.get());

    }
}

请忽略使用可调用和可运行的代码,而不是使用一种类型。所以这是我对这个准则的解释:
假设t1先抓住锁,这意味着t2正在等待锁被释放
t1级 signal() 然后它打印它的消息,然后在 c1.await() 有了这个逻辑,t2永远不应该打印它的消息,因为t1正在等待,而没有 unlock() 预计起飞时间
但令我惊讶的是,它按我所希望的方式工作,每个线程轮流打印其消息,即:
t1级
t2级
t1级
t2级
等等
我不明白的另一件事是 InterruptedException 从来没有发生过 printStackTrace() 从未达到!
有人能解释一下这里发生了什么事吗?

4ioopgfo

4ioopgfo1#

使用这个逻辑,t2永远不应该打印它的消息,因为t1正在等待并且没有解锁
我想你缺少的是 condition.await() 解锁 lock 从哪来的 condition ,然后它保证重新锁定 lock 在它回来之前。

相关问题