【问题标题】:ReentrantLock not giving expected resultReentrantLock 没有给出预期的结果
【发布时间】:2015-05-07 13:56:18
【问题描述】:

我使用线程(等待和通知)功能创建了一个生产者消费者程序。代码是 -

/**
 *  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();



    }

}

我正在尝试使用 ReentrantLock 执行此代码,但它给了我以下错误 -

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)

我在这里做错了吗?当我将 Message.java 中的方法标记为同步时,它可以完美运行。我们可以仅使用可重入锁运行此代码吗??

【问题讨论】:

  • 这是因为 wait()notify() 要求您拥有对象监视器,即同步您调用它们的任何内容。
  • @Kayaman 可以用可重入锁完成吗??
  • 我在博客中读到“ReentrantLock 提供与隐式锁相同的可见性和排序保证,由 Java 中的同步关键字获取”所以我尝试在没有同步方法或任何同步块的情况下执行此操作。有可能吗??
  • 这不是重复的问题@Kayaman,这里我不想使用同步块或同步方法,我想使用锁来运行。

标签: java concurrency locking


【解决方案1】:

Object.waitObject.notify 连接到内部锁定功能,与 synchronized 块和方法一起使用。

如果要使用Locks,则不能使用这两种方法。相反,您必须create a Condition 并在其上调用await(),这应该与在同一个Condition 实例上调用signal() 的另一个线程配对。请注意,与Object.waitObject.notify 不同,每个Lock 可以有多个Condition,并且等待特定条件的线程将被调用signal 的线程唤醒 > Condition 实例。

但是,与内部锁定功能一样,您必须在调用 Condition 上的方法之前拥有关联的锁定。如果是ReadWriteLock,您必须拥有写锁。

不幸的是,Conditions 继承了 Object 的方法 waitnotify,所以千万不要混淆它们,这需要特别小心,因为名称难以区分,wait 和 @ 987654346@.

documentation of Condition 包含一个完整的示例。我只是拿起一个代码片段来说明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();
}

【讨论】:

    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 2021-01-06
    • 2018-12-08
    • 1970-01-01
    相关资源
    最近更新 更多