icn*_*icn 24 java multithreading locking
我有点担心等待并通知/ notifyAll.
我知道每个java对象都有一个锁.我知道等待将释放其他线程的锁.通知/ notifyall怎么样?notify/notifyAll会释放它为其他线程持有的锁吗?
Dan*_*rov 34
不 - notify
/ notifyAll
不要像wait
那样释放锁.唤醒的线程无法运行,直到调用的代码notify
释放其锁定.
这就是Javadoc所说的:
线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒.然后线程等待,直到它可以重新获得监视器的所有权并继续执行.
Was*_*RAR 15
wait()告诉调用线程放弃监视器并进入休眠状态,直到某个其他线程进入同一个监视器并调用notify().
notify()唤醒在同一个对象上调用wait()的线程.
notifyAll()唤醒在同一个对象上调用wait()的所有线程.优先级最高的线程将首先运行.
lui*_*7up 11
我不同意那些说notifyAll()
释放对象的锁定的人,等待和通知线程正在同步.
一个例子:
Consumer
class包含一个块:
synchronized(sharedObject){
if(sharedObject.isReadyToConsume() == false){
sharedObject.wait();
}else {
sharedObject.doTheThing();
System.out.println("consumer consuming...");
}
Run Code Online (Sandbox Code Playgroud)
}
场景:Consumer类获取对sharedObject对象的锁定,独占进入(它在同步块内部),并且看到sharedObject还没有准备就绪(没有消耗:))并且它wait()
在sharedObject上调用方法.这样它就会释放锁(在那里停止执行!)并等待另一个线程(生产者可能)调用sharedObject.notify();
或通知时继续通知sharedObject.notifyAll();
.收到通知后,它会从wait()行继续
它是sharedObject,用于跟踪要求通知的线程.当一些Thread调用sharedObject.notifyAll()方法时,sharedObject将通知等待的线程被唤醒...现在,棘手的部分是一个线程在到达其synchronized(sharedObject)的末尾时自然释放对象的锁定{}阻止.问题是如果我在该块中调用notifyAll()会发生什么?notifyAll()唤醒等待的线程,但锁仍然由刚刚调用notifyAll()的线程拥有
查看Producer片段:
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...");
Run Code Online (Sandbox Code Playgroud)
}
如果notifyAll()将释放锁定,那么在Consumer类已经开始使用sharedObject之后,"awake ..."将被打印出来.情况并非如此......输出显示在Producer退出同步块后,Consumer正在使用sharedObject ...
假设一群读者想要读取某些资源的更新值,该值将由 Writer 更新。那么 Reader 怎么知道 Resource Fields 已经被 Writer 更新了。
因此,为了在公共资源上同步 Readers 和 Writers 之间的这种情况,使用了 Object 类的三个最终方法。
等待: 读者想要读取资源的更新值,他们向资源对象注册,即当更新发生在同一对象上时,当 Writer 通知它时,读者将尝试获取资源锁并读取更新的资源。- 等待仅当 Reader 有锁定对象时被调用,在我们的例子中它是资源。- 一旦调用了wait 方法,Reader 就会释放锁定对象。- 现在只有相同的注册对象(资源)阅读器才会收到通知信号。- 如果Reader 调用wait on Object,这与用于发送通知的Object Writer 不同,Reader 将永远不会收到通知信号。- 一旦 Reader(s) 被通知,现在 Reader(s) 将尝试对锁的内容(其中一个获得锁)读取资源的更新值。类似地,其他 Readers 也轮流获取锁并读取更新的值。
Notify : Writer 进入 Synchronized Block,获取锁后执行他的业务逻辑,更新资源对象,一旦资源对象更新,就会通知正在等待同一个锁的等待线程(读者)。- 仅向一个等待的线程发出通知信号,这是由底层 Java 线程管理器决定的 - 一旦 Writer 发出信号通知(),那么这并不意味着 Reader 立即匆忙读取更新值。首先 writer 必须释放 Lock,一旦它从 Synchronized block 出来就会释放 Lock。一旦 Lock 被释放并通知等待的线程,然后 [In case of notify()] 通知 Thread 将获取 Lock[Released by Writer]然后进入同步块并从他离开的地方完成[即wait()之后的语句]。
通知所有人: 在notifyAll 中,所有注册了资源锁的线程都会收到通知。- 一旦notifyAll() 被触发,所有等待同一个锁的线程都会得到信号并准备好争用锁。- 一旦 Writer 完成其作业并释放锁,任何一个 Reader 都将获取锁[哪个线程,再次由底层 Java 线程管理器实现决定]。- 一旦 Reader 获得锁,它将进入同步块,他离开的地方[即在 wait() 方法之后] 执行它的任务,并在完成同步块后释放锁。- 现在其他剩余的线程将尝试获取锁,它们中的任何一个都会获取它,进入同步块,完成其任务然后释放锁。- 这个过程将一直持续到所有注册读者完成那里的工作。
现在我们将看到它的代码。我们也将讨论守则。:
代码基本概述:它由三个类组成
资源.java
public class Resource {
private String mesg;
public void setMesg(String mesg){
this.mesg =mesg;
}
public String getMesg(){
return this.mesg;
}
}
Run Code Online (Sandbox Code Playgroud)
等待线程任务
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
WriterThreadTask.java
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.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
线程演示程序
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();
}
}
Run Code Online (Sandbox Code Playgroud)
代码观察: