[英]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執行此代碼,但它給了我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)
我在這里做錯什么了嗎? 當我在Message.java中將方法標記為同步時,它可以正常工作。 我們只能使用可重入鎖運行此代碼嗎?
Object.wait
和Object.notify
連接到內部鎖定功能,該功能與synchronized
塊和方法一起使用。
如果要使用Lock
,則不能使用這兩種方法。 相反,您必須創建一個Condition
並在其上調用await()
,該條件應與在同一Condition
實例上另一個調用signal()
線程配對。 請注意,與Object.wait
和Object.notify
不同,每個Lock
可以具有多個Condition
,並且在特定Condition
實例上調用signal
的線程將喚醒等待特定條件的線程。
但是,與內部鎖定功能一樣,您必須擁有關聯的鎖定,然后才能在Condition
上調用方法。 如果是ReadWriteLock
,則您必須擁有寫鎖。
不幸的是, Condition
繼承了Object
wait
和notify
方法,因此永遠不要混淆它們,這一點很重要,由於很難區分名稱wait
和await
,因此需要特別注意。
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(); }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.