synchronized既可以对方法实现同步,也可以对代码块实现同步,示列如下:
// 未同步的方法public void test() {}// 同步的方法pubilc synchronized void test() {}//synchronized 也可以用在一个代码块上,看public void test() { synchronized(obj) { System.out.PRintln("==="); }}使用synchronized代码块,可以只对需要同步的代码进行同步,这样可以提高效率。 synchronized也可以配合Object对象的wait()/notify()/nitifyAll()一起使用。如下列子所示:
package jalonTest;/* Produce线程打印A,Consumer线程打印B。实现ABABAB交替打印。 模拟生产者生产数据后,唤醒消费者消费数据。*/public class Test { static class Consumer implements Runnable { public void run() { // TODO Auto-generated method stub int count = 10; while(count > 0) { synchronized (Test. obj) { try { Test. obj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System. out.print( "B"); count --; Test. obj.notify(); // 主动释放对象锁 } } } } static class Produce implements Runnable { public void run() { // TODO Auto-generated method stub //想想这里为什么要休眠一会呢? try { Thread.sleep(1000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } int count = 10; while(count > 0) { synchronized (Test. obj) { //System.out.print("count = " + count); System. out.print( "A"); count --; Test. obj.notify(); try { Test. obj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } public static final Object obj = new Object(); public static void main(String[] args) { new Thread( new Produce()).start(); new Thread( new Consumer()).start(); }}Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){…}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。
想想在Produce线程中为什么要sleep一会?去掉试试,是否每次都能输出ABABABAB呢? 若不休眠存在一种可能,Produce在notify完毕时,Consumer还没进入wait状态,那就没得玩了。后续Produce会一直等待Consumer的notify而Consumer也在等待Produce的notify,这就是死锁!
新闻热点
疑难解答