一。 java线程同步原理
java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。
当一个线程调用一个对象的同步方法时,JVM会检查该对象的monitor。如果monitor没有被占用,那么这个线程就得到了monitor的占有权,可以继续执行该对象的同步方法;如果monitor被其他线程所占用,那么该线程将被挂起,直到monitor被释放。
当线程退出同步方法调用时,该线程会释放monitor,这将允许其他等待的线程获得monitor以使对同步方法的调用执行下去。
注意:Java对象的monitor机制和传统的临界检查代码区技术不一样。java的一个同步方法并不意味着同时只有一个线程独占执行,但临界检查代码区技术确实会保证同步方法在一个时刻只被一个线程独占执行。Java的monitor机制的准确含义是:[color=red]任何时刻,对一个[color=red]指定object对象[/color]的某同步方法只能由一个线程来调用。[/color]
[color=red]java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。[/color]
二。 wait()、notify(),notifyAll()的使用
obj.wait()方法将使本线程挂起,并释放obj对象的monitor。只有其他线程调用obj对象的notify()或notifyAll()时,才可以被唤醒。
obj.notifyAll()方法唤醒所有该obj对象相关的沉睡线程,然后被唤醒的众多线程开始竞争obj对象的monitor占有权,最终得到的那个线程会继续执行下去,但其他线程还将继续等待。
obj.notify()方法是随机唤醒一个沉睡线程。
wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
如:
synchronized(x){
x.notify()
//或者wait()
}
[color=red]以上内容说明了为什么调用wait(),notify(),notifyAll()的线程必须要拥有obj实例对象的monitor占有权。
每个对象实例都有一个等待线程队列。这些线程都是等待对该对象的同步方法的调用许可。对一个线程来说,有两种方法可以进入这个等待线程队列。一个是当其他线程执行同步方法时,自身同时也要执行该同步方法;另一个是调用obj.wait()方法。
当同步方法执行完毕或者执行wait()时,其他某个线程将获得对象的访问权。当一个线程被放入等待队列时,必须要确保可以通过notify()的调用来解冻该线程,以使其能够继续执行下去。[/color]
三。 wait()与sleep()的区别:
sleep()函数是Thread类的静态函数,不涉及到线程间同步概念,仅仅为了让一个线程自身获得一段沉睡时间。sleep可以在任何地方使用。
wait函数是object类的函数,要解决的问题是线程间的同步,该过程包含了同步锁的获取和释放,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。
注意,线程调用notify()之后,只有该线程完全从 synchronized代码里面执行完毕后,monitor才会被释放,被唤醒线程才可以真正得到执行权。
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()
的功能.因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了.
先看java doc怎么说:
wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.
notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由作为此对象监视器的所有者的线程来调用.
"当前的线程必须拥有此对象监视器"与"此方法只应由作为此对象监视器的所有者的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj之内).
调用对像wait方法后,当前线程释放对像锁,进入等待状态.直到其他线程(也只能是其他线程)通过notify 方法,或 notifyAll.该线程重新获得对像锁.
继续执行,记得线程必须重新获得对像锁才能继续执行.因为synchronized代码块内没有锁是寸步不能走的
java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。
当一个线程调用一个对象的同步方法时,JVM会检查该对象的monitor。如果monitor没有被占用,那么这个线程就得到了monitor的占有权,可以继续执行该对象的同步方法;如果monitor被其他线程所占用,那么该线程将被挂起,直到monitor被释放。
当线程退出同步方法调用时,该线程会释放monitor,这将允许其他等待的线程获得monitor以使对同步方法的调用执行下去。
注意:Java对象的monitor机制和传统的临界检查代码区技术不一样。java的一个同步方法并不意味着同时只有一个线程独占执行,但临界检查代码区技术确实会保证同步方法在一个时刻只被一个线程独占执行。Java的monitor机制的准确含义是:[color=red]任何时刻,对一个[color=red]指定object对象[/color]的某同步方法只能由一个线程来调用。[/color]
[color=red]java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。[/color]
二。 wait()、notify(),notifyAll()的使用
obj.wait()方法将使本线程挂起,并释放obj对象的monitor。只有其他线程调用obj对象的notify()或notifyAll()时,才可以被唤醒。
obj.notifyAll()方法唤醒所有该obj对象相关的沉睡线程,然后被唤醒的众多线程开始竞争obj对象的monitor占有权,最终得到的那个线程会继续执行下去,但其他线程还将继续等待。
obj.notify()方法是随机唤醒一个沉睡线程。
wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
如:
synchronized(x){
x.notify()
//或者wait()
}
[color=red]以上内容说明了为什么调用wait(),notify(),notifyAll()的线程必须要拥有obj实例对象的monitor占有权。
每个对象实例都有一个等待线程队列。这些线程都是等待对该对象的同步方法的调用许可。对一个线程来说,有两种方法可以进入这个等待线程队列。一个是当其他线程执行同步方法时,自身同时也要执行该同步方法;另一个是调用obj.wait()方法。
当同步方法执行完毕或者执行wait()时,其他某个线程将获得对象的访问权。当一个线程被放入等待队列时,必须要确保可以通过notify()的调用来解冻该线程,以使其能够继续执行下去。[/color]
三。 wait()与sleep()的区别:
sleep()函数是Thread类的静态函数,不涉及到线程间同步概念,仅仅为了让一个线程自身获得一段沉睡时间。sleep可以在任何地方使用。
wait函数是object类的函数,要解决的问题是线程间的同步,该过程包含了同步锁的获取和释放,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。
注意,线程调用notify()之后,只有该线程完全从 synchronized代码里面执行完毕后,monitor才会被释放,被唤醒线程才可以真正得到执行权。
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()
的功能.因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了.
先看java doc怎么说:
wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.
notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由作为此对象监视器的所有者的线程来调用.
"当前的线程必须拥有此对象监视器"与"此方法只应由作为此对象监视器的所有者的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj之内).
调用对像wait方法后,当前线程释放对像锁,进入等待状态.直到其他线程(也只能是其他线程)通过notify 方法,或 notifyAll.该线程重新获得对像锁.
继续执行,记得线程必须重新获得对像锁才能继续执行.因为synchronized代码块内没有锁是寸步不能走的