Java notify/notifyall是否释放所持有的锁
我对等待和通知有点困惑 我知道每个java对象都有一个锁。我知道等待将释放其他线程的锁。notify/notifyall怎么样?notify/notifyAll是否释放它为其他线程持有的锁?Java notify/notifyall是否释放所持有的锁,java,multithreading,locking,Java,Multithreading,Locking,我对等待和通知有点困惑 我知道每个java对象都有一个锁。我知道等待将释放其他线程的锁。notify/notifyall怎么样?notify/notifyAll是否释放它为其他线程持有的锁? wait()告诉调用线程放弃监视器并进入睡眠状态,直到其他线程出现 线程进入同一监视器并调用notify() notify()唤醒在同一对象上调用wait()的线程 notifyAll()唤醒在同一对象上调用wait()的所有线程。这个 最高优先级的线程将首先运行 否--通知/通知所有人不要像等待那样释放锁
- wait()告诉调用线程放弃监视器并进入睡眠状态,直到其他线程出现 线程进入同一监视器并调用notify()
- notify()唤醒在同一对象上调用wait()的线程
- notifyAll()唤醒在同一对象上调用wait()的所有线程。这个 最高优先级的线程将首先运行
通知
/通知所有人
不要像等待
那样释放锁。在调用notify
的代码释放其锁之前,唤醒的线程无法运行
这就是Javadoc所说的:
线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行
我必须不同意那些说
notifyAll()
释放对象上的锁的人,在该对象上等待线程和通知线程正在同步
例如:
消费者
类包含一个块:
synchronized(sharedObject){
if(sharedObject.isReadyToConsume() == false){
sharedObject.wait();
}else {
sharedObject.doTheThing();
System.out.println("consumer consuming...");
}
}
场景:Consumer类获取sharedObject对象的锁,以独占方式进入(它位于同步块内),并看到sharedObject尚未准备就绪(无需消费:),它调用sharedObject
上的wait()
方法。这样,当另一个线程(可能是生产者)调用sharedObject.notify()时,它会释放锁(在那里停止执行!),并等待通知继续执行代码>或sharedObject.notifyAll()代码>。收到通知后,它将从等待()行继续
是sharedObject跟踪请求通知它的线程。当一些线程调用sharedObject.notifyAll()方法时,sharedObject将通知等待的线程唤醒。。。
现在,棘手的部分是线程在到达同步(sharedObject){}块的末尾时自然地释放对象的锁。问题是如果调用该块中的notifyAll(),会发生什么notifyAll()唤醒等待的线程,但锁仍然属于刚刚调用了notifyAll()的线程。
请看生产者代码段:
synchronized(sharedObject){
//We are exlusively working with sharedObject and noone can enter it
[... changing the object ...]
sharedObject.notifyAll(); //notifying the waiting threads to wake up
Thread.sleep(1000); //Telling the current thread to go to sleep. It's holding the LOCK
System.out.println("awake...");
}
如果notifyAll()将释放锁,那么在使用者类已经开始使用sharedObject之后,“唤醒…”将被打印出来。事实并非如此。。。输出显示生产者退出其同步块后消费者正在消费sharedObject
- wait()-释放锁并在收到通知时继续下一行
- notify(),notifyAll()-不要释放锁。它们只是使等待的线程再次可运行(而不是空闲)。他们将有权在
当前线程到达其同步块和线程的末尾
scheduleder告诉他们锁已被释放。争夺
锁又开了
为了澄清我的理解,并为所有人提供一个释放锁的示例,我在调用notify()/NotifyAll()后向以下代码添加了print语句:
由于输出getSharedChar能够在setSharedChar之前出现,因此调用notifyAll()可以立即释放锁,或者不需要重新输入同步的getSharedChar()函数。锁可能仍然存在,但是如果您可以在没有锁的情况下重新输入函数,有什么区别?
我可以看到类似的输出将notifyAll()替换为notifyAll()。这是在64位Windows 7系统上的Java 1.7.015上完成的。假设一群读者想要读取某些资源的更新值,这些值将由Writer更新。然后,读者如何知道资源字段已由作者更新
因此,为了在公共资源上的读写器之间同步此类案例,使用了对象类的三种最终方法
- 等等
- 通知()
- notifyAll()
等待:读卡器希望读取资源的更新值,他们向资源对象注册,即当更新发生在同一对象上时,当写入器通知它时,读卡器将尝试获取资源锁并读取更新的资源。
-仅当读卡器具有Lock对象时才调用Wait,在本例中,它是资源。
-一旦调用wait方法,读取器就会释放锁对象。
-现在,只有同一注册对象(资源)的读卡器才会收到通知信号。
-若读取器调用wait-on对象,这与用于发送通知的对象编写器不同,读取器将永远不会得到通知信号。
-一旦通知了读卡器,现在读卡器将尝试为锁读取内容(其中一个获得了锁)并读取资源的更新值。类似地,其他读取器也可以获得锁并读取更新的值。
-一旦读卡器读取了更新的值,执行业务逻辑并从同步块中出来,读卡器将释放锁,以便其他读卡器可以获取它
通知:写入程序进入同步块,在获取锁执行其业务逻辑后,更新资源对象,一旦更新资源对象,它将通知等待的线程(Reade
class ThreadDemo {
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
class Shared {
private char c = '\u0000';
private boolean writeable = true;
synchronized void setSharedChar(char c) {
while (!writeable)
try {
wait();
} catch (InterruptedException e) {
}
this.c = c;
writeable = false;
notifyAll();
System.out.println("setSharedChar notify() called - still in synchronized block.");
}
synchronized char getSharedChar() {
while (writeable)
try {
wait();
} catch (InterruptedException e) {
}
writeable = true;
notifyAll();
System.out.println("getSharedChar notify() called - still in synchronized block.");
return c;
}
}
class Producer extends Thread {
private Shared s;
Producer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting producer thread.");
for (char ch = 'A'; ch <= 'Z'; ch++) {
System.out.println("Producer thread getting ready to create a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
s.setSharedChar(ch);
System.out.println(ch + " produced by producer.");
}
}
}
class Consumer extends Thread {
private Shared s;
Consumer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting consumer thread.");
char ch;
do {
System.out.println("Consumer thread getting ready to read a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
ch = s.getSharedChar();
System.out.println(ch + " consumed by consumer.");
} while (ch != 'Z');
}
}
...
F produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
F consumed by consumer.
Consumer thread getting ready to read a char.
setSharedChar notify() called - still in synchronized block.
G produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
setSharedChar notify() called - still in synchronized block.
G consumed by consumer.
public class Resource {
private String mesg;
public void setMesg(String mesg){
this.mesg =mesg;
}
public String getMesg(){
return this.mesg;
}
}
public class WaitThreadTask implements Runnable {
private Resource resource;
public WaitThreadTask(Resource resource){
this.resource = resource;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Reading Updated Value By : " +Thread.currentThread().getName() );
//We need to Take care to get the updated value, so waiting for writer thread to update value.
try {
//Release resource Lock & wait till any notification from Writer.
resource.wait();
System.out.println("Waiting is Over For : "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Read Updated Value
System.out.println("Updated Value of Resource Mesg :" + resource.getMesg() + " Read By :" +Thread.currentThread().getName());
}
}
}
public class WriterThreadTask implements Runnable{
private Resource resource;
public WriterThreadTask(Resource resource){
this.resource = resource;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Updating Resource By : " + Thread.currentThread().getName());
//Updating resource Object Message
resource.setMesg("Hi How are You !!!");
resource.notify();
//resource.notifyAll();
//Once Writer Comes Out from Synch Block, Readers will Content to read the values.
System.out.println("Task Done By Writer Thread.");
}
}
}
public class ThreadDemo {
public static void main(String args[]){
//Create Single Resource Object, which can act as Lock on Writer and Readers.
Resource lock = new Resource();
//Three Readers and One Writer runnable Tasks.
Runnable taskR1 = new WaitThreadTask(lock);
Runnable taskR2 = new WaitThreadTask(lock);
Runnable taskR3 = new WaitThreadTask(lock);
Runnable taskW1 = new WriterThreadTask(lock);
Thread t1 = new Thread(taskR1, "Reader1");
Thread t2 = new Thread(taskR2, "Reader2");
Thread t3 = new Thread(taskR3, "Reader3");
Thread t4 = new Thread(taskW1, "Writer1");
t1.start();
t2.start();
t3.start();
/*try{
Thread.sleep(5000);
} catch(InterruptedException e){
e.printStackTrace();
}*/
t4.start();
}
}
public class ProducerConsumerInJava {
public static void main(String args[]) {
System.out.println("How to use wait and notify method in Java");
System.out.println("Solving Producer Consumper Problem");
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out .println("Queue is full, " +
"Producer thread waiting for " + "consumer to take
something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out .println("Queue is empty," +
"Consumer thread is waiting" +
" for producer thread to put something in queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
How to use wait and notify
method in Java Solving Producer Consumper Problem
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : -1692411980
Producing value : 285310787
Producing value : -1045894970
Producing value : 2140997307
Producing value : 1379699468
Producing value : 912077154
Producing value : -1635438928
Producing value : -500696499
Producing value : -1985700664
Producing value : 961945684
Queue is full, Producer thread waiting for consumer to take something from
queue Consuming value : -1692411980
Consuming value : 285310787
Consuming value : -1045894970
Consuming value : 2140997307
Consuming value : 1379699468
Consuming value : 912077154
Consuming value : -1635438928
Consuming value : -500696499
Consuming value : -1985700664
Consuming value : 961945684
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : 118213849