wait,notify,notifyAll常见面试问题

(2)wait为什么需要在同步代码块里使用,而sleep不需要
主要是为了防止死锁和永久等待的发生,使通信变得可靠,如果不放在同步代码块里面很有可能在第一个线程wait()之前,cpu切换到另一个线程执行,而另一个线程里面执行了所有的notify(),然后又切回来执行wait()但是设计的逻辑是想执行完wait()之后再执行notify()去唤醒它,可是在没有synchronized保护之后就可以在执行wait()之前突然切换进第二个线程方法执行nortify()再切换回来,这样对方都已经把notify()都执行完毕了,这个导致刚进入wait()状态的线程永远没有人去唤醒它,导致死锁的发生。
sleep本身是针对自己单独线程的,和其他关系并不大,所以并不需要放到同步代码块去做。

(2)为什么线程通信的方法wait(),notify()和notifyaAll()被定义在Object里?而sleep()定义在Thread里?
主要是因为我们在java中的wait(),notify()和notifyaAll()是锁级别的操作,锁是属于某一个对象的,每一个对象的对象头中都是含有几位用来保存锁的状态的,所以这个锁实际上是绑定在某一对象中,而并不是线程中。同样道理我们反过来想假设定义这几个方法在线程中,就会造成很大的局限性。我们经常会遇到某一个线程持有多个锁,并且这些锁之间是相互配合的,如果定义在Thread类里面就没有办法去实现这些灵活的逻辑了。所以Java所提供的原始的锁对于每一个对象都是适用的,他就把这样的方法定义在object里面。

(3)wait()方法是属于object对象的,那调用Thread.wait()会怎么样?
我们把它当做一个普通的锁是没有问题的,我们可以把一个类的实例当做一把锁去做它的wait()方法和notify,但是对于Thread这个类它非常特殊,就是线程退出的时候它会自动地区执行notify(),我们可以在JVM的源码中去看到这部分,这样会使我们设计的流程受到干扰,所以我们创建锁对象的时候不要用Thread类,它不适合作为锁对象,其他的类都比较适合,我们可以用普通的object类去实现就足够了。

(4)如何选择用notify()还是notifyAll()?
主要还是考虑到是要唤醒多个线程还是唤醒一个线程就够了。

(5)notifyAll()之后所有的线程都会再次抢夺锁,如果抢夺失败怎么办?
假设有五个线程都处于WAITING状态现在都唤醒了,同时去抢这把锁,但是只有一个线程能抢到这把锁。没有抢到锁的线程还是回到WAITING状态等待锁释放再去抢或者说再去等待调度器的调度,直到自己拿到这把锁去做下一步的操作。

(6)能不能用suspend()和resume()来阻塞线程可以吗?为什么?
这些方法由于安全问题已经被弃用了,这个功能完全被wait()和notify()代替了。

你可能感兴趣的:(wait,notify,notifyAll常见面试问题)