zoukankan      html  css  js  c++  java
  • JUC 一 ReentrantReadWriteLock

    java.util.concurrent.locks

    ReentrantLock是独占锁,一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生
    ReentrantReadWriteLock读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
    在读锁和写锁的获取过程中支持中断 。Condition只有在写锁中用到(读锁是不支持Condition)

    简介

    一个线程要想同时持有写锁和读锁,必须先获取写锁再获取读锁;写锁可以“降级”为读锁;读锁不能“升级”为写锁。

    线程进入读锁的前提条件(在线程持有读锁的情况下,该线程不能取得写锁):

    1. 没有其他线程的写锁

    线程进入写锁的前提条件( 在线程持有写锁的情况下,该线程可以继续获取读锁):

    1. 没有其他线程的读锁
    2. 没有其他线程的写锁

    读写锁有以下三个重要的特性:
    (1)公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
    (2)重进入:读锁和写锁都支持线程重进入。
    (3)锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。

    基本方法

    public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {}
    
    ReentrantReadWriteLock实现了接口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();
    }
    
    
    ReentrantReadWriteLock
    
    //支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平
    public ReentrantReadWriteLock() {
        this(false);
    }
     
    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }
    
    
    public int getReadLockCount():当前读锁被获取的次数,但不是占用该锁的线程数,也就是说,一个线程如果n次获取该锁,该方法返回n,而不是1。
    
    public int getReadHoldCount():当前线程获取读锁的次数。
    
    public boolean isWriteLocked():判断写锁是否被获取。
    
    public int getWriteHoldCount():当前线程获取写锁的次数。
    
    
    ReadLock 
    
    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        //持有的AQS对象
        private final Sync sync;
    
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
    
        //获取共享锁
        public void lock() {
            sync.acquireShared(1);
        }
    
        //获取共享锁(响应中断)
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }
    
        //尝试获取共享锁
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }
    
        //释放锁
        public void unlock() {
            sync.releaseShared(1);
        }
    
        //新建条件
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }
    
        public String toString() {
            int r = sync.getReadLockCount();
            return super.toString() +
                    "[Read locks = " + r + "]";
        }
    }
    

    示例

    public class ReadWriteLock {
    
    	static ReadWriteLock lock=new ReentrantReadWriteLock();
    
    	static Lock read=lock.readLock();
    	static Lock write=lock.writeLock();
    
    	static HashMap<String, Object> map=new HashMap<String, Object>();
    
    	static Object get(String key){
    		read.lock();
    		try {
    			return map.get(key);
    		} finally {
    			read.unlock();
    		}
    	}
    
    	static void put(String key,Object value){
    		write.lock();
    		try {
    			map.put(key, value);
    		} finally {
    			write.unlock();
    		}
    	}
    
    	static void clear(){
    		write.lock();
    		try {
    			map.clear();
    		} finally {
    			write.unlock();
    		}
    	}
    }
    

    锁降级示例

    锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。

    	static Object putAndget(String key,Object value){
    		write.lock();
    		try {
    			read.lock();
    			map.put(key, value);
    		} finally {
    			write.unlock();
    		}
    		try {
    			return map.get(key);
    		} finally {
    			read.unlock();
    		}
    		
    	}
    
  • 相关阅读:
    IOS-- UIView中的坐标转换
    iphone练习之手势识别(双击、捏、旋转、拖动、划动、长按)UITapGestureRecognizer
    Storm与Spark Streaming比较
    Python程序的常见错误(收集篇)
    Python画图笔记
    如何在论文中画出漂亮的插图?
    别老扯什么Hadoop了,你的数据根本不够大
    保险与互联网结合拉开序幕
    关于数学
    R--基本统计分析方法(包及函数)
  • 原文地址:https://www.cnblogs.com/loveer/p/11413516.html
Copyright © 2011-2022 走看看