java - java中线程通信的锁与条件

标签 java multithreading locking java-threads

我是一个java初学者,我在学习时写了下面的代码Thread在Java中。我想,如果我锁定Resource.set()并注释掉Lock.unlock()Resource.out() 中的代码无法执行,因为当我想执行 out 方法时无法解锁。顺便说一句,我是否注释掉 set() 中的解锁或在 out() ,程序将这样执行:

Thread[Thread-1,5,main]....Produce....chicken1
Thread[Thread-2,5,main]....Consume..........chicken1
Thread[Thread-0,5,main]....Produce....chicken2
Thread[Thread-3,5,main]....Consume..........chicken2 ......

我想了很久,也想不明白。我刚刚学习,可能理解有误,希望大家帮忙。 请原谅我糟糕的英语。非常感谢。我的代码在这里:

package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadStudying {

public static void main(String[] args) {
    Resource r = new Resource();
    Thread t0 = new Thread(new Producer(r));
    Thread t1 = new Thread(new Producer(r));
    Thread t2 = new Thread(new Consumer(r));
    Thread t3 = new Thread(new Consumer(r));

    t0.start();
    t1.start();
    t2.start();
    t3.start();
}

static class Resource {
    private String name;
    private int count = 1;
    boolean isOut = false;

    Lock lock = new ReentrantLock();
    Condition pro_con = lock.newCondition();
    Condition consu_con = lock.newCondition();

    public void set(String name) {
        lock.lock();
        try {
            while (isOut) {
                try {
                    pro_con.await();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            this.name = name + count;
            System.out.println(Thread.currentThread() + "....Produce...." + this.name);
            count++;

            isOut = true;
            consu_con.signal();
        }
        finally {
            lock.unlock();
        }
    }

    public void out() {
        lock.lock();
        try {
            while (!isOut) {
                try {
                    consu_con.await();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(Thread.currentThread() + "....Consume.........." + this.name);

            isOut = false;
            pro_con.signal();
        }
        finally {
            //lock.unlock();
        }
    }
}

static class Producer implements Runnable {
    Resource r;

    Producer(Resource r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            r.set("chicken");

            try {
                Thread.sleep(500);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

static class Consumer implements Runnable {
    Resource r;

    Consumer(Resource r) {
        this.r = r;
    }


    @Override
    public void run() {
        while (true) {
            r.out();
            try {
                Thread.sleep(500);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  }
}

最佳答案

在生产者和消费者中,您都重复调用lock.await

while (true) {
    //
}

来自doc ,当您调用lock.await时:

The lock associated with this Condition is atomically released

所以,无论你是否注释掉lock.unlock,生产者和消费者都不会被阻塞。

P.S.使用下面的代码来记录有关获取和释放锁定的更多详细信息:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadStudying {

public static void main(String[] args) {
    Resource r = new Resource();
    Thread t0 = new Thread(new Producer(r), "Producer 1");
    Thread t1 = new Thread(new Producer(r), "Producer 2");
    Thread t2 = new Thread(new Consumer(r), "Consumer 1");
    Thread t3 = new Thread(new Consumer(r), "Consumer 2");

    t0.start();
    t1.start();
    t2.start();
    t3.start();
}

static class Resource {
    private String name;
    private int count = 1;
    boolean isOut = false;

    Lock lock = new ReentrantLock();
    Condition pro_con = lock.newCondition();
    Condition consu_con = lock.newCondition();

    public void set(String name) {
        System.out.println(Thread.currentThread() + "before lock");
        lock.lock();
        System.out.println(Thread.currentThread() + "get lock");
        try {
            while (isOut) {
                try {
                    System.out.println(Thread.currentThread() + "release lock");
                    pro_con.await();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            this.name = name + count;
            System.out.println(Thread.currentThread() + "....Produce...." + this.name);
            count++;

            isOut = true;
            consu_con.signal();
        }
        finally {

        }
    }

    public void out() {
        System.out.println(Thread.currentThread() + "before lock");
        lock.lock();
        System.out.println(Thread.currentThread() + "get lock");
        try {
            while (!isOut) {
                try {
                    System.out.println(Thread.currentThread() + "release lock");
                    consu_con.await();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(Thread.currentThread() + "....Consume.........." + this.name);

            isOut = false;
            pro_con.signal();
        }
        finally {
            //lock.unlock();
        }
    }
}

static class Producer implements Runnable {
    Resource r;

    Producer(Resource r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            r.set("chicken");

            try {
                Thread.sleep(500);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

static class Consumer implements Runnable {
    Resource r;

    Consumer(Resource r) {
        this.r = r;
    }


    @Override
    public void run() {
        while (true) {
            r.out();
            try {
                Thread.sleep(500);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  }
}

关于java - java中线程通信的锁与条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48879440/

相关文章:

java - java中同步方法的实现和错误行为

java - kubernetes 中 Pod 之间基于 Cookie 的 session 持久性

java - 注册时 SIP 错误

svn - 如何锁定svn

java - 如果只有一个线程写入,多个线程读取,是否需要加一些锁或同步?

java - 如何为服务器端的每个 websocket session 创建相互映射?

c# - .NET 多线程访问共享登录 session

c - 生产者-消费者队列中出现奇怪的死锁

java - ThreadMXBean.dumpAllThreads() 最大深度

java - Hazelcast CP 子系统 FencedLock 内存使用情况