黑马程序员技术交流社区

标题: 线程中调用wait为什么一定要在同步代码块中? [打印本页]

作者: 邱成    时间: 2012-9-17 23:53
标题: 线程中调用wait为什么一定要在同步代码块中?
本帖最后由 邱成 于 2012-9-18 21:31 编辑

学习线程,在做个练习

public class Blocked extends Thread {
public Blocked() {
  start();
}

public void run() {
  try {
   wait();
  } catch (InterruptedException e) {
    ...
  }
}
public static void main(String[] args) {
  new Blocked();
}
}

跑起来坏掉了

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:474)
at Blocked.run(Blocked.java:8)

把wait()放到同步代码块中就可以了:
   synchronized (this) {
    wait();
   }

这是为什么呢?
作者: 黑马张旭明    时间: 2012-9-18 00:24
     这是因为waite()和notify() 必须在synchronized 方法或块中调用。
    waite()和sleep吧()不同的是在释放CPU的时候同时也释放锁,而和synchronized中有锁,有锁才可以释放。
作者: 吴通    时间: 2012-9-18 01:22
计算机在执行程序的时候并不是同步的,而是通过高频率的切换达到一种我们看到的同步
在多线程中,我们的程序在运行时并不是每次都由一条线程从头到尾执行完再由另一条
线程;来执行的,这样就会出现我们意外的结果
为了解决这个问题,可以通过线程的同步
线程的同步包括同步代码块和同步函数
通过同步,只有一条线程把同步代码块中的或者同步函数中的代码执行完毕之后,下一条线程才能
执行。解决了安全问题。

但是当多条线程同时执行时,我们需要这几条线程依次执行才能符合我们的要求,而当一条线程执
行完之后,它也有机会也可能再次抢到计算机的CPU执行权,这样就会连续的执行,和我们的要求
不符合。例如:我们有生产和消费两条线程,我们需要生产一次消费一次
这时,我们就需要通过多线程的等待唤醒机制来实现(也即wait和notify),通过设置标签,线程执行完之后
把标签置反,同时唤醒另外的线程,再次抢夺CPU执行权的时候,就会因为标签不符而等待(wait),这样就
达到了线程依次执行的目的。

为什么用wait而不用sleep呢?
wait()是用来锁定一个对象的,在调用这个notify()方法前,他后面的代码永远不会被执行。这种锁定不能够自动解锁,
你必须在另一个线程中调用这个对象的notify()方法。
而sleep()方法会在休息到设定时间之后自动唤醒

所以,从上面可以看出wait是在同步里面使用的

作者: 赵永康    时间: 2012-9-18 18:10
我们在调用wait()方法的时候,当前线程此时必须监听一个对象,等待另一个去notify()直到他醒来。然后改线程才能去继续执行。就是说必须放在synchronized中
你说的情况 我也试过,查了API文档 才发现是这样的。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2