zoukankan      html  css  js  c++  java
  • ReentrantLock(排他锁)

      在多线程操作时。保证一块共享资源的原子性。第一想到的就是用synchronized关键字

    在jdk5提供一个更灵活更强大的 ReentrantLock 

    使用reentrantLock.lock();获得锁  使用reentrantLock.unlock();释放锁

    public class ReentrantLockTest {
        ReentrantLock reentrantLock = new ReentrantLock();
    
        public void add(Object data) throws InterruptedException {
            try {
                reentrantLock.lock();
                System.out.println("模拟新增耗时");
                Thread.sleep(2000);
                System.out.println("新增完毕");
            } finally {
                // TODO: handle finally clause
                reentrantLock.unlock();
            }
    
        }
    
        public void get() throws InterruptedException {
            
            try {
                reentrantLock.lock();
                System.out.println("模拟获取");
                Thread.sleep(1000);
                System.out.println("新增完毕");
            } finally {
                // TODO: handle finally clause
                reentrantLock.unlock();
            }
        }
        public static void main(String[] args) {
            final ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLockTest.add(1);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLockTest.get();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }).start();;
        }

    synchronized与ReentrantLock区别

    1.synchronized是交给jvm来调度的。ReentrantLock是通过java代码控制的

    2.在synchronized在很多线程竞争的时候会使性能大大下降ReentrantLock在很多线程竞争是不会

    3.ReentrantLock必须配合finally 否则容易产生死锁

    ReentrantLock reentrantLock = new ReentrantLock();
    
        public void Test1() {
            reentrantLock.lock();
            /*
             * 执行逻辑
            */
            Test2();
        }
        public void Test2() {
            reentrantLock.unlock();
        }

    5.ReentrantLock可以进行公平锁选择

    什么情况下选用ReentrantLock

    1.某个线程在等待一个锁的控制权的这段时间需要中断 tryLock

    public class ReentrantLockTest {
        ReentrantLock reentrantLock = new ReentrantLock();
    
        public void add(Object data) throws InterruptedException {
            try {
                reentrantLock.lock();
                
                Thread.sleep(10000);
                System.out.println("模拟新增耗时");
            
            } finally {
                // TODO: handle finally clause
                reentrantLock.unlock();
            }
    
        }
    
        public void get() throws InterruptedException {
            
            try {
                reentrantLock.tryLock(1000, TimeUnit.MILLISECONDS);//尝试获得锁1000毫秒 获取不到放弃
                System.out.println("模拟获取");
                Thread.sleep(1000);
                System.out.println("获取完毕");
            } finally {
                // TODO: handle finally clause
                reentrantLock.unlock();
            }
        }
        public static void main(String[] args) {
            final ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLockTest.add(1);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLockTest.get();
                    
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("执行其他业务逻辑");
                }
            },"t2").start();;
        }
    }

    第一个线程获取锁 等待5秒。当reentrantLock.tryLock(1000, TimeUnit.MILLISECONDS) 会尝试获得锁 若果1秒之内没获取 抛出异常 继续往下执行

    打印

    模拟获取
    获取完毕Exception in thread "t2" 
    java.lang.IllegalMonitorStateException
        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
        at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source)
        at com.bjsxt.height.concurrent019.ReentrantLockTest.get(ReentrantLockTest.java:32)
        at com.bjsxt.height.concurrent019.ReentrantLockTest$2.run(ReentrantLockTest.java:56)
        at java.lang.Thread.run(Unknown Source)
    模拟新增耗时


    2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程 

    public static void main(String[] args) throws InterruptedException {
            final ReentrantLock reentrantLock = new ReentrantLock();
            final Condition condition1= reentrantLock.newCondition();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLock.lock();
                        condition1.await();
                        System.out.println("线程1往下执行");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }finally {
                        reentrantLock.unlock();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        reentrantLock.lock();
                        Thread.sleep(5000);
                        condition1.signal();
                        
                
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }finally {
                        reentrantLock.unlock();
                    }
                }
            },"t2").start();
            Thread.sleep(2000);
            //取消 condition1等待
        }
     reentrantLock.newCondition()可以new多个 。可以通过reentrantLock.signalAll()唤醒所有等待的condition


    3.具有公平锁功能,每个到来的线程都将排队等候

     ReentrantLock reentrantLock = new ReentrantLock(true) 则为公平所
  • 相关阅读:
    re
    response.xpath
    response.css
    mongovue无法显示collection的问题
    window下安装scrapy
    openCV 图片的处理
    sql server 日期时间操作
    怎样在visual studio 2005 让客户端的recv函数不阻塞
    c# winform 程序用126邮箱发邮件
    MiniDump类笔记
  • 原文地址:https://www.cnblogs.com/LQBlog/p/8987626.html
Copyright © 2011-2022 走看看