ReentrantLock 没有给出预期的结果
ReentrantLock not giving expected result
我使用线程(等待和通知)功能创建了一个生产者消费者程序。代码是-
/**
* 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 中的方法标记为同步时,它工作得很好。我们可以 运行 此代码仅使用可重入锁吗??
Object.wait
和 Object.notify
连接到内部锁定功能,与 synchronized
块和方法一起使用。
如果要用Lock
s,这两种方法就不能用了。相反,您必须在同一个 Condition
实例上 create a Condition
and call await()
on it, which should be paired with another thread calling signal()
。请注意,与 Object.wait
和 Object.notify
不同,每个 Lock
可以有多个 Condition
并且等待特定条件的线程将被调用 [=24= 的线程唤醒] 在同一个 Condition
实例上。
但是,与内在锁定功能一样,在 Condition
上调用方法之前,您必须拥有关联的锁。如果是 ReadWriteLock
,您必须拥有写锁。
不幸的是,Condition
s 从 Object
继承了方法 wait
和 notify
,因此切勿将它们混淆,这需要特别小心,因为很难区分名字,wait
和 await
.
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();
}
我使用线程(等待和通知)功能创建了一个生产者消费者程序。代码是-
/**
* 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 中的方法标记为同步时,它工作得很好。我们可以 运行 此代码仅使用可重入锁吗??
Object.wait
和 Object.notify
连接到内部锁定功能,与 synchronized
块和方法一起使用。
如果要用Lock
s,这两种方法就不能用了。相反,您必须在同一个 Condition
实例上 create a Condition
and call await()
on it, which should be paired with another thread calling signal()
。请注意,与 Object.wait
和 Object.notify
不同,每个 Lock
可以有多个 Condition
并且等待特定条件的线程将被调用 [=24= 的线程唤醒] 在同一个 Condition
实例上。
但是,与内在锁定功能一样,在 Condition
上调用方法之前,您必须拥有关联的锁。如果是 ReadWriteLock
,您必须拥有写锁。
不幸的是,Condition
s 从 Object
继承了方法 wait
和 notify
,因此切勿将它们混淆,这需要特别小心,因为很难区分名字,wait
和 await
.
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(); }