JAVA的进程同步是经过synchronized()来实现的,须要说明的是,JAVA的synchronized()方法相似于操做系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程没法访问该内存,从而实现JAVA中简单的同步、互斥操做。明白这个原理,就能理解为何synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字表明类的一个对象,因此其内存锁是针对相同对象的互斥操做,而static成员属于类专有,其内存空间为该类全部成员共有,这就致使synchronized()对static成员加锁,至关于对类加锁,也就是在该类的全部成员间实现互斥,在同一时间只有一个线程可访问该类的实例。若是只是简单的想要实如今JAVA中的线程互斥,明白这些基本就已经够了。但若是须要在线程间相互唤醒的话就须要借助Object.wait(), Object.nofity()了。java
wait与notify是java同步机制中重要的组成部分。结合与synchronized关键字使用,能够创建不少优秀的同步模型。
synchronized(this){}等价与public synchronized void method(){.....}
同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每一个类只有一个,若是static的方法被synchronized关键字修饰,则在这个方法被执行前必须得到类锁;对象锁类同。(static synchronized是类级别的,非static的synchronized和synchronized块都是对象级别的,即做用在同一new出来的对象上)
首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在做用等同于synchronized(obj){......}的内部才可以去调用obj的wait与notify/notifyAll三个方法,不然就会报错:
java.lang.IllegalMonitorStateException: current thread not owner
在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次得到了去得到对象锁的权利。
因此,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并容许它去得到锁,notifyAll是唤醒全部等待这个对象的线程并容许它们去得到对象锁,只要是在synchronied块中的代码,没有对象锁是步履维艰的。其实唤醒一个线程就是从新容许这个线程去得到对象锁并向下运行。 顺便说一下notifyall,虽然是对每一个wait的对象都调用一次notify,可是这个仍是有顺序的,每一个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,须要注意一下。ide
应用实例:函数
创建三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就能够很方便的解决。this
package cn.com.thread; /** * Description: <交替打印10次ABC>. <br> * <p> * <使用说明> * </p> * Makedate:2014-4-12 下午2:14:19 * * @author gaowenming * @version V1.0 */ public class WaitAndNotifyTest { /** * 描述 : <描述函数实现的功能>. <br> * <p> * <使用方法说明> * </p> * * @param args */ public static void main(String[] args) { final PrintABC printAbc = new PrintABC(); // 循环加载外层 for (int i = 0; i < 10; i++) { new Thread(new Runnable() { @Override public void run() { try { printAbc.printA(); // printA } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { printAbc.printB();// printB } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { printAbc.printC();// printC } catch (Exception e) { e.printStackTrace(); } } }).start(); } } } /** * * * @Description: 交替打印10次ABC * @author gaowenming * @date 2014-4-12 下午2:17:11 * */ class PrintABC { // 定义全局变量 boolean a = true; boolean b = false; boolean c = false; public synchronized void printA() throws Exception { // 用while,表示一直等待 while (!a) { this.wait(); } System.out.print("A"); a = false; b = true; // 执行完后唤醒其余等待的线程 notifyAll(); } public synchronized void printB() throws Exception { while (!b) { this.wait(); } System.out.print("B"); b = false; c = true; notifyAll(); } public synchronized void printC() throws Exception { while (!c) { this.wait(); } System.out.println("C"); c = false; a = true; notifyAll(); } }
运行结果:spa
ABC操作系统
ABC线程
ABCcode
ABC对象
ABC进程
ABC
ABC
ABC
ABC
ABC