synchronized和lock锁(一)

1.声明synchronized方法的方式,这个称之为方法锁或者对象锁。

synchronized void f(){/*....*/}
synchronized void g(){/*....*/}

    全部的对象都自动含有单一的锁(也称为监视器,前面阅读Thread源码有提到监视器)。当在对象上调用任意synchronized方法时,此对象都被加锁,这时该对象上的其余synchronized方法只有等到前一个方法调用完毕释放了锁以后才能被调用。对于前面的方法,若是某个任务对对象调用了f(),对于同一个对象而言,只有等到f()调用结束并释放了锁以后,其余任务才能调用f()或者g()。因此,对于某个特定的对象来讲,其全部的synchronized方法共享同一个锁,这能够被用来防止多个任务同时访问被编码对象内存。java

    一个任务能够屡次得到对象锁,也就是锁可重入。是指,一个方法在同一个对象上调用了第二个方法,后者又调用了同一个对象上的另一个方法,就是发生锁的重入。JVM负责跟踪对象被枷锁的次数。若是一个对象被解锁也就说锁被彻底释放,其计数变为0。在任务第一次给对象加锁时,计数变为1。每当这个相同的任务在这个对象上得到锁的时候,计数都会递增。显然,只有先得到了锁的任务才能容许继续得到锁。每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被彻底释放,此时别的任务就能够继续使用此资源。并发

2.类锁,能够看作特殊的对象锁,锁的是类对象

    针对每一个类,也有一个锁,做为Class对象的一部分,因此synchronized static方法能够在类的范围内防止对static数据的并发访问。ide

3.显式使用Lock对象

    基本上,当你使用关键字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());
    }

}
相关文章
相关标签/搜索