黑马程序员技术交流社区
标题:
关于wait()的小疑惑
[打印本页]
作者:
胥文
时间:
2013-2-18 23:22
标题:
关于wait()的小疑惑
wait():表示释放cpu执行权,也释放锁
synchronized (obj)
{
while(!condition)
{
obj.wait();//假如当线程A执行到这时,会释放锁,并释放资源,而当线程A再次获得CPU执行权的
//时候,然后获得锁(
就是对这个在代码块内部获得锁有点疑问,之前都是获得锁才能进来但是按照这个逻辑好像是在代码块中获得锁
),
// 在执行下面的语句
System.out.println("hello");
}
}
作者:
冯佩
时间:
2013-2-19 03:11
锁是为了让代码同步,而避免出现多线程并发执行代码的错误,获取锁才能进来是没错的,这里此时的情况是获取锁进来释放了锁以后又重新获取锁。A停在了代码块内部,故再次获取锁时也是在内部获得。在哪里里获得锁并不十分重要,重要的是在代码块中是否同步安全。
作者:
赵熠东(赵东东)
时间:
2013-2-19 22:20
线程执行到obj.wait();时不会释放锁!至于你说的资源就不知道是什么了,执行wait()方法只是线程放入等待池中等待而已,我觉着此时并不存在你说的“释放资源、释放锁”情况
作者:
铿锵科技
时间:
2013-2-20 10:46
JDK1.5 中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait,notify notifyAll,替换了Condition对象。
该对象可以Lock锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
作者:
黑马-王言龙
时间:
2013-2-20 11:20
这是一个坑
作者:
张晋瑜
时间:
2013-2-20 12:16
额,你这理解得离谱了。
怎么这么写就是:”(就是对这个在代码块内部获得锁有点疑问,之前都是获得锁才能进来但是按照这个逻辑好像是在代码块中获得锁)“了呢?
作者:
张晋瑜
时间:
2013-2-20 12:20
标题:
我来回答,版主,把分给我吧,楼主有什么问题看问再问.....
本帖最后由 zhangjinyu1991 于 2013-2-20 12:24 编辑
同步实现
synchronized
虽然有
”同步”的意思,但它实现的首先是互斥机制,讲究的是消除对临界资源访问的竞争,而不关心访问线程之间的步调。而要实现同步:不仅要消除对临界资源访问的竞争,还要关心访问线程之间的步调。
所以,用以下公式来表达同步机制的实现再合适不过了:
Java
的同步机制
=
存取共享资源的互斥机制
+
线程间的通信机制
存取共享资源的互斥机制我们已经知道了用
synchronized
来实现了,那线程间的通信怎么实现呢?
线程间的通信
线程间的通信通过Object
类中的方法:wait()
、notify()
、notifyAll()
来实现。
wait()
:暂停当前线程的执行,并释放所持有的锁,进入等待状态。
notify()
:唤醒一个等待线程。
notifyAll()
:唤醒所有等待的线程。
这三个方法都是
Object
类的final
方法,所以不能被重写
。
这三个方法必须要与synchronized
一起使用,只能
直接或间接
地用于临界区中。
注意:
我在网上就看到了有位博友写的一篇文章(http://blog.csdn.net/zyplus/article/details/6672775
),他说”从语法角度来说就是Obj.wait(),Obj.notify
必须在synchronized(Obj){...}
语句块内“,这是直接用于临界区,其实也可以:比如说用在临界资源的一个方法put()
中,但临界区中有调用这个方法就可以了(我下面的那个生产者-
消费者案例就是这样用的)。
下面再来看看一个有关线程同步的经典案例:生产者-消费者问题
/**
* 生产者与消费者问题
* 分析
* 仓库类Warehouse 生产者类Producer 消费者类Consumer
* 临界资源->仓库类Warehouse 临界区->存取产品的动作(代码)
* @author jin
*
*/
public class ProducerConsumer {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
WareHouse buffer=new WareHouse();
(new Producer(buffer)).start();
(new Consumer(buffer)).start();
}
}
class WareHouse{
private int product; // 仓库中的产品
private boolean isEmpty=true; // 标记仓库是否为空
public void put(int product_put){ //向仓库放入产品
// 若仓库不为空,则进入等待状态;
while(!isEmpty){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 若为空,则向仓库放入产品(放入了产品当能就要标记仓库不为空咯)并发出通知
this.product=product_put;
this.isEmpty=false;
notify();
}
public int get(){ //从仓库取出产品
// 若仓库为空,取产品这个动作的线程自然要进入等待状态了
while(isEmpty){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 若仓库不为空,返回产品(取出了产品仓库就空了,就要标记仓库为空)并发出通知
isEmpty=true;
notify();
return this.product;
}
}
class Producer extends Thread{
private WareHouse buffer; // 将要访问的临界资源
public Producer(WareHouse buffer) {
// TODO Auto-generated constructor stub
this.buffer=buffer;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (buffer) {
for(int i=1; i<=5; i++){ // 假设生产5个产品:1、2、3、4、5
buffer.put(i);
System.out.println("存入产品:"+i);
}
}
}
}
class Consumer extends Thread{
private WareHouse buffer; // 将要访问的临界资源
public Consumer(WareHouse buffer) {
// TODO Auto-generated constructor stub
this.buffer=buffer;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (buffer) {
for(int i=1; i<=5; i++){ // 生产了5个产品,我们也就5次去拿产品
System.out.println("取出产品:"+buffer.get());
}
}
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2