JAVA中线程互斥和同步
2015-02-11 23:08
85 查看
线程交互知识点需要从java.lang.Object的类的三个方法来学习:
void notify()
唤醒在此对象监视器上等待的单个线程。
void notifyAll()
唤醒在此对象监视器上等待的所有线程。
void wait()
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
当然,wait()还有另外两个重载方法:
void wait(long timeout)
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
void wait(long timeout, int nanos)
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
以上这些方法是帮助线程传递线程关心的时间状态。
关于等待/通知,要记住的关键点是:
必须从同步环境内调用wait()、notify()、notifyAll()方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。
wait()、notify()、notifyAll()都是Object的实例方法。与每个对象具有锁一样,每个对象可以有一个线程列表,他们等待来自该信号(通知)。线程通过执行对象上的wait()方法获得这个等待列表。从那时候起,它不再执行任何其他指令,直到调用对象的notify()方法为止。如果多个线程在同一个对象上等待,则将只选择一个线程(不保证以何种顺序)继续执行。如果没有线程等待,则不采取任何特殊操作。
千万注意:
当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程荣然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁变得可用。
如何理解线程同步:那么我们就要来理解Wait Set,
Wait Set,见名知义,就是休息区,线程的休息区等待室。
共享资源又被称为临界区,Critical Section。当一个线程想要访问这个共享资源时,需要获得这个共享资源的锁,使用synchronized的关键字给加上锁,这个时候就只有这个线程可以访问这个共享资源了,当线程运行发现某些条件不能够满足时,可以调用这个加锁对象的wait方法,这个时候线程就会释放掉这个锁资源,进入等待区Wait Set,这样别的线程就可以来竞争这个锁资源,当需要唤醒等待区中的线程时就可以调用notify方法,使等待区中的一个线程离开重新回到可以竞争锁资源的状态,这个唤醒的线程是由底层算法实现的,我们无法控制,如果需要唤醒等待区中的多个线程可以使用notifyAll方法。
void notify()
唤醒在此对象监视器上等待的单个线程。
void notifyAll()
唤醒在此对象监视器上等待的所有线程。
void wait()
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
当然,wait()还有另外两个重载方法:
void wait(long timeout)
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
void wait(long timeout, int nanos)
导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
以上这些方法是帮助线程传递线程关心的时间状态。
关于等待/通知,要记住的关键点是:
必须从同步环境内调用wait()、notify()、notifyAll()方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。
wait()、notify()、notifyAll()都是Object的实例方法。与每个对象具有锁一样,每个对象可以有一个线程列表,他们等待来自该信号(通知)。线程通过执行对象上的wait()方法获得这个等待列表。从那时候起,它不再执行任何其他指令,直到调用对象的notify()方法为止。如果多个线程在同一个对象上等待,则将只选择一个线程(不保证以何种顺序)继续执行。如果没有线程等待,则不采取任何特殊操作。
/** * 计算输出其他线程锁计算的数据 * * @author leizhimin 2008-9-15 13:20:38 */ public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB(); //启动计算线程 b.start(); //线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者 synchronized (b) { try { System.out.println("等待对象b完成计算。。。"); //当前线程A等待 b.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("b对象计算的总和是:" + b.total); } } }
/** * 计算1+2+3 ... +100的和 * * @author leizhimin 2008-9-15 13:20:49 */ public class ThreadB extends Thread { int total; public void run() { synchronized (this) { for (int i = 0; i < 101; i++) { total += i; } //(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒 notify(); } } }
等待对象b完成计算。。。 b对象计算的总和是:5050
千万注意:
当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程荣然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁变得可用。
如何理解线程同步:那么我们就要来理解Wait Set,
Wait Set,见名知义,就是休息区,线程的休息区等待室。
共享资源又被称为临界区,Critical Section。当一个线程想要访问这个共享资源时,需要获得这个共享资源的锁,使用synchronized的关键字给加上锁,这个时候就只有这个线程可以访问这个共享资源了,当线程运行发现某些条件不能够满足时,可以调用这个加锁对象的wait方法,这个时候线程就会释放掉这个锁资源,进入等待区Wait Set,这样别的线程就可以来竞争这个锁资源,当需要唤醒等待区中的线程时就可以调用notify方法,使等待区中的一个线程离开重新回到可以竞争锁资源的状态,这个唤醒的线程是由底层算法实现的,我们无法控制,如果需要唤醒等待区中的多个线程可以使用notifyAll方法。
相关文章推荐
- Java线程(四):JUC包线程互斥与同步以及读写锁
- Java多线程编程--(3)线程互斥、同步的理解
- java多线程总结笔记4——线程互斥与同步
- Java同步机制浅谈――synchronized对代码作何影响?
- Windwos下的线程互斥和同步
- 反编译:java代码中含有同步和异常的反编译前后代码对照的一个例子(xiongjy)
- Java线程基本用法与同步问题
- JAVA线程的高级同步
- 破除java神话之四:同步代码等同于断面(critical section)
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份
- Java Thread实现读写同步
- Java同步机制浅谈――synchronized对代码作何影响? (转载)
- Java同步机制浅谈――synchronized对代码作何影响?
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份
- Windwos下的线程互斥和同步
- Java线程及同步(synchronized)样例代码 [转]
- Java单例对象同步问题探讨
- Java同步问题
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份