Java 多线程并发 ReentrantLock锁

一、synchronized 和  ReentrantLock 的区别 

        synchronized 和 ReentrantLock ,都是加锁方式同步,一个线程正在执行,另一个线程必须等待。

        使用分析: ReentrantLock 是Lock 的实现类,在 多线程竞争的环境下,更有性能优势,使用更加的灵活,

                    但是需要手动的去开启锁和释放锁,尽量放在 try catch finally 中 是适用于修饰代码块

                    synchronized  不需要手动释放锁,可以作用于 方法和 代码块 

        1.等待可中断

                当持有锁的线程长期不释放的时候,正在等待的线程可以放弃等待,转而处理其他的事情。

                具体实例 : 有两个线程 Thread1 和 Thread2 ,Thread1 获得了对象的锁,正在执行任务,另一个线程正在等待,Thread1释放锁。

                        若使用syncheronized :Thread2 会阻塞 等待。

                        若使用 ReentrantLock :Thread2 等待长时间后,放弃等待,转而执行其他的任务。

        2。公平锁

                按照申请的时间先后顺序,依次执行。 synchronized 是非公平锁  ReentrantLock可以在构造方法中传入 true 或 false 来修改是否是 公平锁和 非公平锁

二、非公平锁

    // synchronized 是 Java 语言的关键字,是原生语法的互斥,需要JVM 实现 ,
    // 而ReentrantLock是JDK1.5之后提供的互斥锁,需要lock() 和unLock(),try()Catch()finally() 配合执行。 
    private ReentrantLock lock = new ReentrantLock();
    public void run() {
        lock.lock(); 
        try{
            for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }finally{
            lock.unlock();
        }
    }

 

  2.1 锁绑定多个条件

      ReentrantLock可以同时绑定多个Condition对象,只需多次调用newCondition方法即可。

      synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含的条件。但如果要和多于一个的条件关联的时候,就不得不额外添加一个锁。

 2.2 线程的安全问题 怎么理解‘

      进程中有多个线程同时在执行,这些线程可能会执行同一段代码,多线程的执行结果和单线程的执行结果是一样的。那么就是线程安全的

 2.3 synchronized 在编译时怎么实现锁机制?

      synchronized 在进行编译的时候,会在同步块的前后,会形成monitorenter 和 monitorexit 两个字节码指令,在执行 

monitorenter  时,回先获取锁,得到锁,锁的计数器就是加一,执行完毕计数器就会减一,释放锁。

 2.4 什么时候选择 ReentrantLock 

        确实有 synchronized 没有的特性时, 可中断等候,时间锁等候。

 

// ThreadPoolExcutor  源码中很地方用到
    /**
     * Rolls back the worker thread creation.
     * - removes worker from workers, if present
     * - decrements worker count
     * - rechecks for termination, in case the existence of this
     *   worker was holding up termination
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            decrementWorkerCount();
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

三、非公平锁和公平锁案例分析

    // 那个线程先运行,那个线程就先得到锁,非公平锁不管
    private void test3() {
        Service service = new Service();
        ThreadClass tcArray[] = new ThreadClass[10];
        for(int i=0;i<10;i++){
            tcArray[i] = new ThreadClass(service);
            tcArray[i].start();
        }
    }
    
    public class Service {
        ReentrantLock lock = new ReentrantLock(true);
        Service() {
        }
    
        void getThreadName() {
            System.out.println(Thread.currentThread().getName() + " 已经被锁定");
        }
    }
    public class ThreadClass extends Thread{
        private Service service;
        ThreadClass(Service service) {
            this.service = service;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName() + " 抢到了锁");
            service.lock.lock();
            service.getThreadName();
            service.lock.unlock();
        }
    }
    //当ReentrantLock设置true,也就是公平锁时
     I/System.out: Thread-5 抢到了锁
     I/System.out: Thread-5 已经被锁定
     I/System.out: Thread-6 抢到了锁
     I/System.out: Thread-6 已经被锁定
     I/System.out: Thread-7 抢到了锁
     I/System.out: Thread-8 抢到了锁
     I/System.out: Thread-7 已经被锁定
     I/System.out: Thread-8 已经被锁定
     I/System.out: Thread-9 抢到了锁
     I/System.out: Thread-9 已经被锁定
     I/System.out: Thread-10 抢到了锁
     I/System.out: Thread-10 已经被锁定
     I/System.out: Thread-11 抢到了锁
     I/System.out: Thread-11 已经被锁定
     I/System.out: Thread-12 抢到了锁
     I/System.out: Thread-12 已经被锁定
     I/System.out: Thread-14 抢到了锁
     I/System.out: Thread-14 已经被锁定
     I/System.out: Thread-13 抢到了锁
     I/System.out: Thread-13 已经被锁定

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值