简体   繁体   English

ReentrantLock没有给出预期的结果

[英]ReentrantLock not giving expected result

I have created a producer consumer program using threads (wait and notify) feature. 我已经使用线程(等待和通知)功能创建了一个生产者使用者程序。 The code is - 该代码是-

/**
 *  Message.java ( Common object )
 */
package threads;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author chouhan_r
 *
 */
public class Message {
    private String message;

    ReentrantLock lock = new ReentrantLock();
    ReentrantLock takelock = new ReentrantLock();
    private boolean empty =true;
    public  void put(String message){
        lock.lock();
        while(!empty){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        empty = false;
        this.message = message;

        notifyAll();
        lock.unlock();
    }

    public String take(){

        takelock.lock();
        while(empty){
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        empty = true;

        notifyAll();
        takelock.unlock();
        return message;

    }


}


/**
 * Producer.java
 */
package threads;

import java.util.Random;

public class Producer implements Runnable{
    private Message message;
    public Producer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        String[] impInfo = {"Hello", "I am here", "why are you doing this ??", "No problem" };
        Random random = new Random();
        for(String str : impInfo){
            message.put(str);
            try {
                Thread.sleep(random.nextInt(3000));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        message.put("Finished");

    }



}

/**
 * Consumer.java
 */
package threads;

public class Consumer implements Runnable{
    private Message message;
    public Consumer(Message message) {
        this.message = message;
    }
    @Override
    public void run() {
        System.out.println(message);
        String msg = message.take();
        while(!"Finished".equalsIgnoreCase(msg)){
            System.out.println(msg);
            msg = message.take();
        }


    }


}

===================== =====================

/**
 * Main Program
 */
package threads;

public class ProConsTest {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new Consumer(message)).start();
        new Thread(new Producer(message)).start();



    }

}

I am trying to execute this code using ReentrantLock but it is giving me followin error - 我正在尝试使用ReentrantLock执行此代码,但它给了我followin错误-

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Unknown Source)
    at threads.Message.take(Message.java:39)
    at threads.Consumer.run(Consumer.java:11)
    at java.lang.Thread.run(Unknown Source)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at threads.Message.put(Message.java:31)
    at threads.Producer.run(Producer.java:16)
    at java.lang.Thread.run(Unknown Source)

Am I doing something wrong here ?? 我在这里做错什么了吗? when I mark methods in Message.java as synchronized it works perfect. 当我在Message.java中将方法标记为同步时,它可以正常工作。 Can we run this code only with the Reentrant lock ?? 我们只能使用可重入锁运行此代码吗?

Object.wait and Object.notify are connected to the intrinsic locking feature, which is used with synchronized blocks and methods. Object.waitObject.notify连接到内部锁定功能,该功能与synchronized块和方法一起使用。

If you want to use Lock s, you can't use these two methods. 如果要使用Lock ,则不能使用这两种方法。 Instead you have to create a Condition and call await() on it, which should be paired with another thread calling signal() on the same Condition instance. 相反,您必须创建一个Condition并在其上调用await() ,该条件应与在同一Condition实例上另一个调用signal()线程配对。 Note that unlike Object.wait and Object.notify , you can have more than one Condition per Lock and threads waiting for a particular condition will be woken up by threads calling signal on the same Condition instance. 请注意,与Object.waitObject.notify不同,每个Lock可以具有多个Condition ,并且在特定Condition实例调用signal的线程将唤醒等待特定条件的线程。

However, as with the intrinsic locking feature, you must own the associated lock before calling a method on a Condition . 但是,与内部锁定功能一样,您必须拥有关联的锁定,然后才能在Condition上调用方法。 In case of a ReadWriteLock , you must own the write lock. 如果是ReadWriteLock ,则您必须拥有写锁。

Unfortunately, Condition s inherit the methods wait and notify from Object , so it's important to never mix them up, which requires special care due to the hard to distinguish names, wait and await . 不幸的是, Condition继承了Object waitnotify方法,因此永远不要混淆它们,这一点很重要,由于很难区分名称waitawait ,因此需要特别注意。

The documentation of Condition contains a complete example. Condition文档包含一个完整的示例。 I just pick up one code fragment illustrating the usage in the put method: 我只是拿起一个代码片段来说明put方法的用法:

 final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); 

...

 lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } 

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

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