synchronized void f(){/*....*/} synchronized void g(){/*....*/}
全部的对象都自动含有单一的锁(也称为监视器,前面阅读Thread源码有提到监视器)。当在对象上调用任意synchronized方法时,此对象都被加锁,这时该对象上的其余synchronized方法只有等到前一个方法调用完毕释放了锁以后才能被调用。对于前面的方法,若是某个任务对对象调用了f(),对于同一个对象而言,只有等到f()调用结束并释放了锁以后,其余任务才能调用f()或者g()。因此,对于某个特定的对象来讲,其全部的synchronized方法共享同一个锁,这能够被用来防止多个任务同时访问被编码对象内存。java
一个任务能够屡次得到对象锁,也就是锁可重入。是指,一个方法在同一个对象上调用了第二个方法,后者又调用了同一个对象上的另一个方法,就是发生锁的重入。JVM负责跟踪对象被枷锁的次数。若是一个对象被解锁也就说锁被彻底释放,其计数变为0。在任务第一次给对象加锁时,计数变为1。每当这个相同的任务在这个对象上得到锁的时候,计数都会递增。显然,只有先得到了锁的任务才能容许继续得到锁。每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被彻底释放,此时别的任务就能够继续使用此资源。并发
针对每一个类,也有一个锁,做为Class对象的一部分,因此synchronized static方法能够在类的范围内防止对static数据的并发访问。ide
基本上,当你使用关键字synchronized关键字时,须要的代码量更少,而且用户出现错误的几率更低,所以一般只有解决特殊任务时才会使用到现实的Lock对象。好比,用synchronized不能尝试获取锁而且最终会获取锁失败,或者尝试着获取锁等待一段时间,这些须要concurrent类库this
abstract class IntGenerator{ private volatile boolean canceled = false; public abstract int next(); public void cancel(){this.canceled =true;} public boolean isCanceled(){return this.canceled;} } class EvenChecker implements Runnable{ private IntGenerator generator; private final int id; public EvenChecker(IntGenerator g,int ident){ generator = g; id = ident; } public void run() { while (!generator.isCanceled()){ int val = generator.next(); if(val%2 != 0){ System.out.println(val + " not even!"); generator.cancel(); } } } public static void test(IntGenerator gp,int count){ System.out.println("Press Contrl-C to exit"); ExecutorService exec = Executors.newCachedThreadPool(); for(int i=0;i<count;i++){ exec.execute(new EvenChecker(gp,i)); } exec.shutdown(); } public static void test(IntGenerator gp){ test(gp,10); } } class SynchronizedEvenGenerator extends IntGenerator{ private int currentVlaue = 0; public synchronized int next() { ++currentVlaue; //当不使用synchronized修饰next方法时,调用该方法能够促使线程同步调用异常发生 //Thread.yield(); //一样说明一个问题Thread。yield即使是让出cpu可是并无释放锁 ++currentVlaue; return currentVlaue; } } class MutexEvenGenerator extends IntGenerator{ private int currentVlaue = 0; private Lock lock = new ReentrantLock(); public int next() { lock.lock(); try{ ++currentVlaue; //当不使用synchronized修饰next方法时,调用该方法能够促使线程同步调用异常发生 Thread.yield(); //一样说明一个问题Thread。yield即使是让出cpu可是并无释放锁 ++currentVlaue; return currentVlaue; }finally { lock.unlock(); } } } public class NesttyMain implements Serializable{ public static void main(String[] args){ // EvenChecker.test(new SynchronizedEvenGenerator()); EvenChecker.test(new MutexEvenGenerator()); } }