回答
使用使一个方法/块一次只能在线程上访问。所以,是的,它是线程安全的。
这两个概念是结合在一起的,而不是相互排斥的。当您使用wait()
时,您需要拥有该对象上的显示器。所以你在这之前需要有synchronized(..)
。使用.wait()
使当前线程停止,直到另一个线程在其等待的对象上调用.notify()
。这是的补充,它只确保只有一个线程将进入块/方法。
有效的Java项目69:“考虑使用等待的难度和 通知正确的,你应该使用更高级别的并发性工具,而不是”。
尽可能避免使用wait()和notify():使用或其他来自java.util.concurrent的实用程序。
因此,在面试中遇到困难之后,我决定再次查找并理解第10亿次。
同步块使代码线程安全。毫无疑问。当wait()和notify()或notifyAll()进来时,就是你试图编写更高效代码的地方。例如,如果你有一个多线程共享的项目列表,那么如果你把它放在一个监视器的同步块中,那么线程线程将不断跳转,并在上下文切换过程中来回运行代码。 。甚至有一个空的列表!
因此wait()在监视器(synchronized(..)中的对象)上用作一种机制来告诉所有线程冷静并停止使用cpu周期,直到进一步通知或notifyAll()为止。
所以像:
synchronized(monitor) {
if(list.isEmpty())
monitor.wait();
}
...somewhere else...
synchronized(monitor){
list.add(stuff);
monitor.notifyAll();
}
要求你总是在一个循环内调用wait(),例如while(list.isEmpty())monitor.wait()如果你想等到实际上有东西被另一个线程放入列表中。 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait() – Arthur
这应该是答案。程序员不能选择哪个同步块应该先行。但等待/通知可以指导哪个块应该先行。 +1。 –
同步块被使用,如果“相同的对象”的2个线程试图accquire锁。由于对象类持有锁,它知道该给谁。然而,如果2个对象(obj1的t1 & t2和obj2的t3 & t4)的2个线程(比如t2和t4)尝试获取该锁,obj1将不知道obj2的锁,并且obj2将不知道obj1的锁。因此使用等待和通知方法。
如:
//example of java synchronized method
class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
两个线程T1和T2属于同一个对象,因此同步工作在这里很好。 然而,
class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();
Table obj1 = new Table();
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj1);
t1.start();
t2.start();
}
}
当你运行上面的程序,同步不会因为每个线程的工作属于不同的对象,因此,你应该使用wait和notify这里。
等待/通知是需要等待一些条件(例如,用户输入)INSIDE一个同步块。
典型用途:
synchronized(obj) {
// do something
while(some condition is not met) {
obj.wait();
}
// do something other
}
让我们假设你不使用的等待()。然后,您必须实现繁忙循环轮询所需的条件,这对性能不利。
synchronized(obj) {
// do something
while(some condition is not met) { // busy loop }
// do something other
}
重要提示:即使一个线程被唤醒通知()或notifyAll的()其他线程,觉醒的线程做不保证立即恢复执行。如果有其他线程在等待在同一个对象上执行同步块,那么唤醒线程应该与线程竞争。
我不确定这是一个好例子。 wait()是一个阻塞方法,所以它不一定在无限循环内。您可以简单地在一个同步块中使用wait(),当满足条件时,可以在另一个同步块中使用notify()来“解除”wait()方法。 – Scarfe
制作方法synchronized有两个作用:
首先,它是不可能的同一对象来交织上同步方法的两个调用。当一个线程正在执行的对象同步方法,来调用同步对于相同的对象块(暂停执行)的方法,直到第一线程中的所有其他线程与对象
其次,当同步方法退出完成,它会自动建立与同一对象的任何后续同步方法调用之间的前后关系。这保证了对所有线程都可见的对象状态的更改。
同步帮助您保护关键代码。
如果你想多线程之间建立通信,则必须使用wait()和notify()/notifyAll()
wait()
:造成当前线程等待,直到其他线程调用notify()方法或notifyAll()方法为这个对象。
notify()
:唤醒正在等待该对象监视器的单个线程。如果任何线程正在等待这个对象,则选择其中一个线程来唤醒。
notifyAll()
:唤醒在该对象监视器上等待的所有线程。线程通过调用其中一个等待方法来等待对象的监视器。
使用wait()和notify()的简单用例:生产者和消费者问题。
消费者线程必须等到生产者线程产生数据。 wait()和notify()在上面的场景中很有用。在一段时间内,引入了更好的替代方案。请参阅此high level concurrency教程页面。
简单来说:
使用守卫保护您的数据的关键部分,并保护您的代码。
使用wait()
和notify()
以及同步如果你想以安全的方式建立多个线程之间的通信,它们是相互依赖的。
相关SE问题:
- 1. 同步函数和同步块之间有什么区别?
- 2. 多线程加入和等待之间的区别,通知
- 3. 等待()/通知()同步
- 4. 同步之间的区别
- 5. 在Makefile中结束带有或没有等号的`define`之间的区别?
- 6. 同步块和条件变量锁之间有什么区别?
- 7. lib和带有autoconf的模块之间有什么区别
- 8. 异步方法 - 等待和返回任务之间的区别
- 9. 等待和异步和任务并行库之间的区别
- 10. 等待Task(ReadFromIO)并等待Task.WhenAll(task1,task2)之间的区别;
- 11. 通知和等待不起作用的同步块
- 12. Java同步对象,等待和通知
- 13. xbee之间没有同步
- 14. 他们之间有区别,如果有,它是什么?
- 15. 5.0之前的c#异步编程没有异步&等待?
- 16. 同步块锁定对象和等待/通知
- 17. 处置之间的区别没有
- 18. 不同进程之间的java等待通知机制
- 19. Java同步游戏:同步&&等待&&通知
- 20. 异步等待任务<T>没有异步/等待
- 21. 异步没有被异步/等待块捕获
- 22. 汇编:声明与''之间的区别和没有它
- 23. 同步(this)和同步(objectReference)之间的区别
- 24. 同步(foo.class)vs同步(SomeClass.class)之间的区别
- 25. 异步并等待:它们不好吗?
- 26. 工作区之间的数据交换没有通知
- 27. 单线程和同步之间有区别吗?
- 28. 在异步方法中返回和等待任务之间的区别
- 29. 有方法之间的java等待
- 30. 有一个功能等待AJAX调用,没有同步AJAX(SJAX)
所以为什么我们需要使用等待/通知的方法呢?一定有一些分歧吧? – Alan
看到更新.... – Bozho
我认为当同步块结束时,它会释放锁。执行同步方法或语句的其他线程将在无法获取锁时阻塞。它也像一个wait()notify()机制,非常相似。 Alan询问wait()和notify()的区别是什么,而不仅仅是普通的同步块结束。 –