zoukankan      html  css  js  c++  java
  • java Lock

    一、Lock锁:

      Lock是一个接口,Lock需要手动的释放锁,Lock锁可以知道是否成功的获取锁。

    二、Lock接口中的方法

      

      获取锁:Lock() tryLock()tyrLock(long time,timeUnit unit)lockInterruptibly()

      释放锁:unlock()

      

     四种获取锁方法的区别:

      1.Lock()这种方法是最常用的方法,

      由于在前面讲到Lock锁必须手动释放锁,并且在发生异常时不会自动释放锁。因此一般来说,使用Lock必须在try{}catch(){}  中。而释放锁的过程放在finally中,以保证锁即使在异常的情况下也能被正常的释放,防止死锁的发生。

      Lock lock = ...;
    
      lock.lock();
    
      try{
    
          //处理任务
    
      }catch(Exception ex){
    
         
    
      }finally{
    
          lock.unlock();   //释放锁
    
      }

      2.tryLock()方法是有返回值的方法,此方法可用来判断是否获取了锁,如果获取了锁,返回值为true,如果获取失败(即锁已被其它线程占用),则返回值为false。也就是说这个方法不会一直原地等待,无论是否拿到锁都会立即返回。

    Lock lock = ...;
    if(lock.tryLock()) {
         try{
             //处理任务
         }catch(Exception ex){
             
         }finally{
             lock.unlock();   //释放锁
         } 
    }else {
        //如果不能获取锁,则直接做其他事情
    }

      3.tryLock(long time,timeUnit time)方法和tryLock() 方法类似,不同的是此方法在拿不到锁会等待一段时间,如果在期限的时间内还拿不到锁,就不再等待,而是返回false。如果一开始或期限时间内拿到锁,就返回true

      4.lockInterruptibly()方法比较特殊,当用西方法获取锁的时候,如果线程处在没有获取到锁,而正在等待获取锁,那么这个线程是可以被中断,即中断线程的等待状态。也就是说,当两个线程同时通过lock.lockInterruptibly()向获取锁时,加入线程A获取了锁,线程B只能等待,那么对线程B调用B.lockInterruptibly() 是中断线程B的等待过程。

    注意:当一个线程获取了锁之后是不会被interrupt()方法打断的,interrupt()可以打断正在阻塞的线程,不可以打断正在执行的进程。

    因此当通过lockInterruptibly()方法获取锁时,如果获取不到,只有进行等待的情况下,是可以响应中断的。而如果使用synchronized修饰的话,当一个线程处于正在等待某个锁的状态没事无法中断的,只能一直等待下去。

    三、ReentrantLock

      

      意思是可重入锁,是Lock接口的实现类。

      来看一个实例

     1.lock()方法

    public class TestLock {
        public static void main(String[] args) {
            Thread1 thread=new Thread1();
            Thread thread1=new Thread(thread);
            Thread thread2=new Thread(thread);
            thread1.start();
            thread2.start();
        }
    }
    class Thread1  implements  Runnable{
        private   Lock lock=new ReentrantLock();
        public void run(){
            lock.lock();
            try{
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName()+"i "+i);
                }
            }catch (Exception  e){
                e.printStackTrace();
            }finally {
              lock.unlock();
            }
        }
    }

     运行结果:

      2.tryLock() 方法的使用

    public class TestLock {
        public static void main(String[] args) {
            Thread1 thread = new Thread1();
            Thread thread1 = new Thread(thread);
            Thread thread2 = new Thread(thread);
            thread1.start();
            thread2.start();
        }
    }
    
    class Thread1 implements Runnable {
        //公用一把锁
        private Lock lock = new ReentrantLock();
    
        public void run() {
    
            if (lock.tryLock()) {
                try {
                    System.out.println(Thread.currentThread().getName()+"获取了锁");
                    for (int i = 0; i < 5; i++) {
                        System.out.println(Thread.currentThread().getName() + "i " + i);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName()+"释放了锁");
                    lock.unlock();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+"获取锁失败");
            }
    
        }
    }

    运行结果:

     

    四、ReadWriteLock

      ReadWriteLock是一个接口,在里面只定义了两个方法:

    public interface ReadWriteLock {
    
        /**
    
         * Returns the lock used for reading.
    
         *
    
         * @return the lock used for reading.
    
         */
    
        Lock readLock();
    
     
    
        /**
    
         * Returns the lock used for writing.
    
         *
    
         * @return the lock used for writing.
    
         */
    
        Lock writeLock();
    
    }

    readLock()方法是用来获取读锁,writelock()是用来获取写锁,也就是将文件的读写操作分开,分成2个锁操作来分配给线程,从而使得多个线程可以同时进行读操锁。

    五、ReentrantReadWriteLock 

      ReentrantReadWriteLock实现了ReadWriteLockReentrantReadWriteLock提供了很多方法,不过最重要的两个方法:readLock()WriteLock()来获取读锁和写锁。

    public class MyReentrantReadWriteLock {
        private ReentrantReadWriteLock rrwl=new ReentrantReadWriteLock();
    
        public static void main(String[] args) {
            MyReentrantReadWriteLock m=new MyReentrantReadWriteLock();
            new Thread(){
                public void run(){
                    m.get(Thread.currentThread());
                }
            }.start();
            new Thread(){
                public void run(){
                    m.get(Thread.currentThread());
                }
            }.start();
        }
        public void get(Thread thread){
            rrwl.readLock().lock();
            try{
                System.out.println(thread.getName()+"得到锁");
                long start=System.currentTimeMillis();
                while(System.currentTimeMillis()-start<=1){
                    System.out.println(thread.getName()+"正在读取文件");
                }
            }finally {
                System.out.println(thread.getName()+"释放锁");
                rrwl.readLock().unlock();
            }
        }
    }

    运行结果:

     

     六、与synchronized的区别

      1)在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降很多,但是ReetrantLock的性能能维持常态。

        2)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;

      3)Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

  • 相关阅读:
    indexDB的用法
    append动态生成的元素,无法触发事件的原因及解决方案
    jquery中attr()和prop()的区别
    arguments.callee
    meter标签度量衡如何改变颜色
    Nginx入门
    linux中的权限管理
    python_面向对象
    ORM
    Flask入门
  • 原文地址:https://www.cnblogs.com/xuesheng/p/7993759.html
Copyright © 2011-2022 走看看