- 浏览: 595982 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
月光杯:
问题解决了吗?
Exceptions in HDFS -
iostreamin:
神,好厉害,这是我找到的唯一可以ac的Java代码,厉害。
[leetcode] word ladder II -
standalone:
One answer I agree with:引用Whene ...
How many string objects are created? -
DiaoCow:
不错!,一开始对这些确实容易犯迷糊
erlang中的冒号 分号 和 句号 -
standalone:
Exception in thread "main& ...
one java interview question
一段时间不用java,这些概念就全混淆了,有必要彻底澄清一下,总结在这里,当然以我的本事,不太可能写出水平较高的总结,这里主要是总结stackoverflow上面高人的言论。
先说sleep() 和 wait()
sleep() method causes the current thread to move from running state to block state for a specified time. If the current thread has the lock of any object then it keeps holding it, which means that other threads cannot execute any synchronized method in that class object.
sleep()这个方法是让当年线程从运行态转入阻塞态一段时间,如果当前线程拥有一些对象的锁,那么这个线程将继续拥有,也就意味着其他线程不能执行那些对象的synchronized方法。
注意,sleep()是Thread类的static方法,假如在一个Synchronized块中调用Thread的sleep()方法,虽然线程休眠,但是对象锁还会存在,
wait() method causes the current thread to go into block state either for a specified time or until notify, but in this case the thread releases the lock of the object (which means that other threads can execute any synchronized methods of the calling object.
wait()方法使当前的线程进入阻塞状态直到一段指定的时间结束或者被唤醒,调用wait()会释放对象的锁,也就意味着其他线程可以执行对象的synchronized方法。
注意,wait()方法是Object类的非静态方法,所以每个对象都可以调用。
wait()的使用
a). wait()必须放在synchronized块之中;
这个我前面有一篇blog刚好说这个的:
http://standalone.iteye.com/blog/788259
要执行wait()当前线程必须要先拿到锁。
b). wait()必须放在一个while loop中;
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
这个是说有可能睡眠的线程被唤醒不是靠的被notify()/notifyAll()或者被中断,或者时间到了,有一种情况叫spurious wakeup, 你可以点进去看一下高人对此种虚假唤醒的解释。总之,因此要将wait放在一个while循环中,每次醒来自己去检查你的条件是否满足了。
Orcacle的文档也讲了:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait(long)
还有另一种情况,看下面这个例子,如果不用while循环会出现什么错误。
(引自:http://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again)
假设这是一个ProducerConsumer类的两个方法,假如Consumer c1进入同步方法并且buffer是空的,c1会被阻塞在X处。这时候假如c2等着要进同步方法,它必须要拿到同步锁才能进来,所以会被阻塞在get()方法的开头处Y;假设Producer p1这时候生成了一个东西添加到buffer里面去了,然后notify(),此时因为wait的只有c1,所以c1会被唤醒,等着去拿同步锁,好继续往下执行。现在的情形是c1和c2都在抢同步锁!再假如c2幸运拿到了,那么c2会完整执行get()方法并且释放同步锁,这时候c1可以拿到,注意假如我们没有while循环,c1此时拿到锁之后直接往下执行,等着它的是一个空的buffer!会报IndexArrayOutOfBoundException!解决的办法就是需要while循环!
notify() vs. notifyAll()
notify() 是唤醒一个线程,notifyAll()是唤醒所有的线程,这个大家都知道。多数时候你应该用notifyAll,有时候如果需要用notifyAll()错用notify()会出错!仍然看上面那个例子。
简化情况,假如buffer的大小是1.
假如有如下的调用顺序:(P代表生产者线程,C代表消费者线程)
1:
P1放1个东西到buffer;
2:
P2准备放--发现已经满了--wait
3:
P3准备放--发现已经满了--wait
4:
C1准备从buffer里取一个,并成功
C2准备从buffer里取一个,阻塞在方法入口
C3准备从buffer里取一个,阻塞在方法入口
5:
C1释放同步锁,调用notify(),退出get方法
P2被唤醒
但是C2在P2之前抢到锁,所以P2会被继续阻塞
C2检查wait条件,发现buffer仍为空,继续阻塞
6:
现在P3,C2,C3都在等待
最终P2拿到锁,放一个东西到buffer, 调用notify,退出
7:
P2唤醒了P3(记住是随机的)
P3检查了一下发现buffer是满的,等待
现在没有任何线程再会调用notify,所有线程会被永远阻塞!死锁产生!
解决方案:将notify替换成notifyAll
先说sleep() 和 wait()
sleep() method causes the current thread to move from running state to block state for a specified time. If the current thread has the lock of any object then it keeps holding it, which means that other threads cannot execute any synchronized method in that class object.
sleep()这个方法是让当年线程从运行态转入阻塞态一段时间,如果当前线程拥有一些对象的锁,那么这个线程将继续拥有,也就意味着其他线程不能执行那些对象的synchronized方法。
注意,sleep()是Thread类的static方法,假如在一个Synchronized块中调用Thread的sleep()方法,虽然线程休眠,但是对象锁还会存在,
wait() method causes the current thread to go into block state either for a specified time or until notify, but in this case the thread releases the lock of the object (which means that other threads can execute any synchronized methods of the calling object.
wait()方法使当前的线程进入阻塞状态直到一段指定的时间结束或者被唤醒,调用wait()会释放对象的锁,也就意味着其他线程可以执行对象的synchronized方法。
注意,wait()方法是Object类的非静态方法,所以每个对象都可以调用。
wait()的使用
a). wait()必须放在synchronized块之中;
这个我前面有一篇blog刚好说这个的:
http://standalone.iteye.com/blog/788259
要执行wait()当前线程必须要先拿到锁。
b). wait()必须放在一个while loop中;
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
这个是说有可能睡眠的线程被唤醒不是靠的被notify()/notifyAll()或者被中断,或者时间到了,有一种情况叫spurious wakeup, 你可以点进去看一下高人对此种虚假唤醒的解释。总之,因此要将wait放在一个while循环中,每次醒来自己去检查你的条件是否满足了。
Orcacle的文档也讲了:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one: synchronized (obj) { while (<condition does not hold>) obj.wait(timeout); ... // Perform action appropriate to condition }
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait(long)
还有另一种情况,看下面这个例子,如果不用while循环会出现什么错误。
(引自:http://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again)
public synchronized void put(Object o) { while (buf.size()==MAX_SIZE) { wait(); // called if the buffer is full (try/catch removed for brevity) } buf.add(o); notify(); // called in case there are any getters or putters waiting } public synchronized Object get() { // Y: this is where C2 tries to acquire the lock (i.e. at the beginning of the method) while (buf.size()==0) { wait(); // called if the buffer is empty (try/catch removed for brevity) // X: this is where C1 tries to re-acquire the lock (see below) } Object o = buf.remove(0); notify(); // called if there are any getters or putters waiting return o; }
假设这是一个ProducerConsumer类的两个方法,假如Consumer c1进入同步方法并且buffer是空的,c1会被阻塞在X处。这时候假如c2等着要进同步方法,它必须要拿到同步锁才能进来,所以会被阻塞在get()方法的开头处Y;假设Producer p1这时候生成了一个东西添加到buffer里面去了,然后notify(),此时因为wait的只有c1,所以c1会被唤醒,等着去拿同步锁,好继续往下执行。现在的情形是c1和c2都在抢同步锁!再假如c2幸运拿到了,那么c2会完整执行get()方法并且释放同步锁,这时候c1可以拿到,注意假如我们没有while循环,c1此时拿到锁之后直接往下执行,等着它的是一个空的buffer!会报IndexArrayOutOfBoundException!解决的办法就是需要while循环!
notify() vs. notifyAll()
notify() 是唤醒一个线程,notifyAll()是唤醒所有的线程,这个大家都知道。多数时候你应该用notifyAll,有时候如果需要用notifyAll()错用notify()会出错!仍然看上面那个例子。
简化情况,假如buffer的大小是1.
假如有如下的调用顺序:(P代表生产者线程,C代表消费者线程)
1:
P1放1个东西到buffer;
2:
P2准备放--发现已经满了--wait
3:
P3准备放--发现已经满了--wait
4:
C1准备从buffer里取一个,并成功
C2准备从buffer里取一个,阻塞在方法入口
C3准备从buffer里取一个,阻塞在方法入口
5:
C1释放同步锁,调用notify(),退出get方法
P2被唤醒
但是C2在P2之前抢到锁,所以P2会被继续阻塞
C2检查wait条件,发现buffer仍为空,继续阻塞
6:
现在P3,C2,C3都在等待
最终P2拿到锁,放一个东西到buffer, 调用notify,退出
7:
P2唤醒了P3(记住是随机的)
P3检查了一下发现buffer是满的,等待
现在没有任何线程再会调用notify,所有线程会被永远阻塞!死锁产生!
解决方案:将notify替换成notifyAll
发表评论
-
ssl 与 java 实例
2014-01-27 10:10 750http://www.iteye.com/topic/1125 ... -
Java NIO
2014-01-10 21:28 703看了这个java nio的教程,明白了什么是Selector. ... -
Why singleton is anti-pattern?
2013-07-03 10:12 873OO Test Other reasons? -
How to generate the serialVersionUID when you implement Serializable interface,j
2013-07-01 10:52 919http://docs.oracle.com/javase/6 ... -
Java Override的两个问题
2013-06-01 11:40 9261: 如果子类中的方法的参数是父类的方法的子类型,那么算不算o ... -
Java常用类API统计
2013-06-01 11:35 0String charAt(int) compareTo( ... -
How many string objects are created?
2013-06-01 10:18 1315This is a very common java inte ... -
使用Java的DelayQueue容易碰到的一个坑
2013-05-27 17:32 6671今天不忙,学习一下java.util.concurrent.D ... -
[leetcode] Balanced Binary Tree
2013-04-28 14:08 1563Check if a binary tree is balan ... -
[leetcode] find median of two sorted arrays
2013-04-26 10:55 1437http://leetcode.com/onlinejudge ... -
[leetcode] word ladder
2013-04-25 15:05 2258Q: Given two words (start and ... -
[leetcode] word ladder II
2013-04-15 07:35 11646http://leetcode.com/onlinejudge ... -
[leetcode] Count and Say
2013-04-12 14:05 2241http://leetcode.com/onlinejudge ... -
Date/Time处理函数总结 [To Do]
2013-04-12 10:46 643几种我所用到的用来处理日期,时间的函数总结。 Perl 1 ... -
[leetcode] Palindrome Partition
2013-04-12 10:25 1308http://leetcode.com/onlinejudge ... -
[leetcode] Palindrome Partitioning II
2013-04-11 16:45 1495http://leetcode.com/onlinejudge ... -
Profiling your Java code using Spring
2013-03-05 15:02 664Quite good article!!! http://w ... -
Java的Generics的几点限制
2012-12-28 15:00 4709参见 http://docs.oracle.com/ ... -
Overriding Method Using Parameter That is a Subclass?
2012-12-27 22:14 877参见 http://www.coderanch.com/t/3 ... -
Java的Generics和c++的Template到底有什么不同?
2012-12-27 16:21 3185先了解Java的Generics: 根据Java的文档,Jav ...
相关推荐
3.wait,notify和notifyAll只能在同步方法或同步代码块中调用,而sleep可以在任何地方调用; 4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。(如果不是在同步方法或同步代码块中调用wait()方法,...
wait()、notify()和notifyAll() wait()和sleep() 线程中断 静态方法(有关同步的细节) 总结 第五章 Java线程编程的例子 数据结构和容器 简单的同步例子 一个网络服务器类 AsyncInputStream类 使用TCP...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。) sleep...
一 基本知识 2 1.1 任务Runnable 2 1.2 线程构造器Threat 2 1.3 执行器Executor 2 1.4 任务中返回值Callable接口 3 1.5 休眠 6 1.6 让步 6 1.7 优先级 6 1.8 后台线程(daemon) 6 ...2.5.3 notify()与notifyAll() 24
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 62、同步和...
描述一下notify和notifyAll区别; synchronized关键字加在静态方法和实例方法的区别; 用锁的注意点; cas机制可能导致的问题ABA,什么是ABA; 程序开多少线程合适; 实现一下DCL(双重检查锁) stream 和 parallel...
42.notify()和 notifyAll()有什么区别? 43.线程的 run()和 start()有什么区别? 44.创建线程池有哪几种方式? 45.线程池都有哪些状态? 46.线程池中 submit()和 execute()方法有什么区别? 47.在 java 程序中怎么...
LeetCode判断字符串是否循环 知识点总结 java基础 1、使用迭代器和for each循环查看集合元素时只能获得元素的值,不能改变元素 ...object的方法:wait(notify,notifyall),thread的方法:(sleep、join),结束
42. notify()和 notifyAll()有什么区别? 16 43. 线程的 run()和 start()有什么区别? 16 44. 创建线程池有哪几种方式? 17 45. 线程池都有哪些状态? 18 46. 线程池中 submit()和 execute()方法有什么区别? 18 49....
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、Overload...
wait()、notify()和notifyAll() 虚假唤醒 Condition 定制化通信 多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) ...
//下面的消费者类对象和生产者类对象所操作的是同一个同步堆栈对象 Producer p1 = new Producer(stack,ce); new Thread(p1).start();//生产者线程启动 Consumer c1 = new Consumer(stack,ce); new Thread(c1)....
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 17、...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
DEF A notify() B wait() C notifyAll() D sleep() E.yield() F.synchronized(this) 7.构造BufferedInputStream的合适参数是哪个? AC A BufferedInputStream B BufferedOutputStream ...
notify notifyAll 78 【多线程】sleep()和wait()分别是哪个类的方法,有什么区别? 79 【多线程】sleep()和yield()的区别 79 【多线程】对synchronized理解?用在代码块和方法上有什么区别? 80 【多线程】Volatile...
第一章程序和程序设计 .......................................................................................................1 §1.1 什么是程序 ?........................................................
只有当别的线程在该对象上调用了 notify()或者notifyAll()方法,"Wait Set"队列中的线程才得到机会去竞争,但是只有一个线程获得对象的Monitor,恢复到运行态。"Wait Set"中的线程在Thread Dump中显示的状态为 in ...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、...
│ 高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │ 高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │ 高并发编程第一阶段29讲、如何实现一个...