Java 并发编程:同步
线程除要对共享数据保证互斥性访问外,往往还需保证线程的操作按照特定顺序进行。
解决多线程按照特定顺序访问共享数据的技术称作同步。同步技术最常见的编程范式是同
步保护块。这种编程范式在操作前先检测某种条件是否成立,如成立则继续操作;如不成
立则有两种选择,一种是简单的循环检测,直至此条件条件成立:
1 public void guardedOperation(){
2 while(!condition_expression){
3 System.out.println("Not ready yet, I have to wait again!");
4 }
5 }
这种方法非常消耗 CPU 资源,任何情况下都不应该使用这种方法。另种更好的方式
是条件不成立时调用 Object.wait 方法挂起当前线程,使它一直等待,直至另一个线程
发出激活事件。当然该事件不一定是当前线程希望等待的事件。
1 public synchronized guardedOperation() {
2 while(!condition_expression) {
3 try {
4 wait();
5 } catch (InterruptedException e) {}
6 }
7 System.out.println("Now, condition met and it is ready!");
8 }
这儿有两点需要特别注意:
1.要在循环检测中等待条件满足,这是因为中断事件并不一定是当前线程所期望的
事件。线程等待被中断后应该继续检测条件,以便决定是否进入下一轮等待。
2.当前线程在对 wait 方法调用时,必须是已经获得 wait 方法所属对象的内部锁。也
就 是 说 , wait 方 法 必 须 在 互 斥 块 或 者 互 斥 方 法 体 内 调 用 , 否 则 就 会 发 生
NotOwnerException 错误。这种限制和前面所说的同步前提是互斥的说法是一致的。
上面代码更通用的写法是:
1 ...
2 synchronized(lock){
3 while(!condition_expression){
4 try{
5 lock.wait();
6 }catch(InterruptedException ie){}
7 }
8 System.out.println("Now, condition met and it is ready!");
9 }
10 ...