• Java多线程_ReentrantLock


    ReentrantLock是重入锁,它与synchronized很像,它是synchronized的加强版,因为它具有一些synchronized没有的功能。
    下面我们看看两者的区别:
    synchronized具有一定的局限性:

    • 当线程尝试获取锁的时候,如果获取不到锁会一直阻塞;
    • 如果获取锁的线程进入休眠或者阻塞,除非当前线程异常,否则其他线程尝试获取锁必须一直等待;
    • 是非公平的。

    而ReentrantLock实现了AQS,可以完成下列功能:

    • 可中断响应;
    • 锁申请等待限时;
    • 公平锁;
    • 与Condition一起使用,实现synchronized与wait/notify的功能。

    引入几个概念:
    提到ReentrantLock,我们不得不明白几个概念:

    • 可重入锁。可重入锁是指同一个线程可以多次获取同一把锁。ReentrantLock和synchronized都是可重入锁。
    • 可中断锁。可中断锁是指线程尝试获取锁的过程中,是否可以响应中断。synchronized是不可中断锁,ReentrantLock则提供了中断功能。
    • 公平锁与非公平锁。公平锁是指多个线程必须按顺序,不许插队。非公平锁允许插队。synchronized是非公平锁,而ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
    • CAS,在前面已经提到。

    使用示例
    具体用法通过简单代码通过代码演示:

    import java.util.concurrent.locks.ReentrantLock;
    
    public class ReentrantLockDemo implements Runnable {
        static ReentrantLock lock = new ReentrantLock();
        static int count = 0;
    
        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    count++;
                } finally {
                    lock.unlock();
                }
            }
    
        }
    
        public static void main(String[] args) {
            ReentrantLockDemo r = new ReentrantLockDemo();
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
            t1.start();
            t2.start();
            try {
                t1.join();
                t2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(count);
            //结果输出:20000
        }
    }

    通过ReentrantLock解决死锁问题:

    import java.util.concurrent.locks.ReentrantLock;
    
    public class KillDeadlockDemo implements Runnable {
        static ReentrantLock lock1 = new ReentrantLock();
        static ReentrantLock lock2 = new ReentrantLock();
        int lock;
    
        public KillDeadlockDemo(int lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                if (lock == 1) {
                    lock1.lockInterruptibly();
                    Thread.sleep(500);
                    lock2.lockInterruptibly();
                } else {
                    lock2.lockInterruptibly();
                    Thread.sleep(500);
                    lock1.lockInterruptibly();
                }
            } catch (InterruptedException e) {
            } finally {
                if (lock1.isHeldByCurrentThread()) {
                    lock1.unlock();
                }
                if (lock2.isHeldByCurrentThread()) {
                    lock2.unlock();
                }
                System.out.println(Thread.currentThread().getName() + "退出!");
            }
    
        }
    
        public static void main(String[] args) {
            KillDeadlockDemo kdd1 = new KillDeadlockDemo(1);
            KillDeadlockDemo kdd2 = new KillDeadlockDemo(2);
            Thread t1 = new Thread(kdd1);
            Thread t2 = new Thread(kdd2);
            t1.start();
            t2.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t2.interrupt();
          /*
           *结果输出:
           *Thread-1退出!
           *Thread-0退出!
           */
        }
    }

    使用 tryLock()或者tryLock(long timeout, TimeUtil unit) 方法进行一次限时的锁等待,也可以解决死锁问题:

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class TryLockDemo implements Runnable {
        static ReentrantLock lock = new ReentrantLock();
    
        @Override
        public void run() {
            try {
                if (lock.tryLock(1, TimeUnit.SECONDS)) {
                    Thread.sleep(1100);
                } else {
                    System.out.println(Thread.currentThread().getName() + "获取锁失败!释放");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
    
        public static void main(String[] args) {
            TryLockDemo td = new TryLockDemo();
            Thread thread1 = new Thread(td);
            Thread thread2 = new Thread(td);
            thread1.start();
            thread2.start();
            try {
                thread1.join();
                thread2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                  //结果输出:Thread-1获取锁失败!释放
        }
    }

    公平锁演示:

    import java.util.concurrent.locks.ReentrantLock;
    
    public class FairLockDemo implements Runnable {
        static ReentrantLock lock = new ReentrantLock(true);
    
        @Override
        public void run() {
            while (true) {
                try {
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() + " get lock");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                } finally {
                    lock.unlock();
                }
            }
        }
    
        public static void main(String[] args) {
            FairLockDemo fld = new FairLockDemo();
            Thread t1 = new Thread(fld);
            Thread t2 = new Thread(fld);
            Thread t3 = new Thread(fld);
            t1.start();
            t2.start();
            t3.start();
    /*
    *Thread-0 get lock
    *Thread-1 get lock
    *Thread-2 get lock
    *Thread-0 get lock
    *Thread-1 get lock
    *Thread-2 get lock
    *..........
    */
        }
    }

    浅谈原理

     请转到:https://www.cnblogs.com/ericz2j/p/13445822.html



  • 相关阅读:
    结婚也可以2.0!
    最近读书清单
    Win7旗舰版中的IIS配置asp.net的运行环境
    Google Chrome浏览器
    MySQL到NoSQL:数据的重思和查询方式的转换
    sqlserver游标概念与实例全面解说
    高效管理ASP.NET的JavaScript库
    如何提取网页中的flash
    如何手动启动tomcat
    tomcat单词缩写
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10292664.html
Copyright © 2020-2023  润新知