java并发工具包-ReadWriteLock

1. 基础知识

  1. 允许同一时刻多个线程的访问;是共享锁的代表锁。同一时刻多个读的线程访问,但是在写线程访问时,所有的读线程和其它写线程还是会被阻塞
  2. 适合的场景是多读少写
  3. 也是重入锁

2. 实现分析

  1. 读写状态的设计:因为需要使用AQS的状态保存多个读线程和一个写线程的状态;而需要使用一个整型变量维护多种状态,就需要“按位切割使用”这个变量,高16位表示读,低16位表示写
  2. 锁降级:
    1. 指的是写锁降级为读锁。过程是:持有写锁,再获取读锁,再释放写锁的过程。
    2. 获取写锁之后,再获取读锁,是否有必要? 是必须的。主要为了保证数据的可见性。若是当前线程不获取读锁,而是直接释放写锁,假设另外一个线程T获取了写锁并修改了数据,那么当前线程无法感知到线程T的数据更新。如果当前线程获取了读锁,即遵循锁降级的步骤,则线程T将会被阻塞,知道当前线程使用完数据并释放了读锁之后,线程T才能获取写锁进行数据更新。
    3. 不支持锁升级(把持读锁,获取写锁,最后是否读锁的过程)。目的也是保证数据可见性,若读锁已被多个线程获取,其中任意线程成功获取了写锁并更新了数据,则其更新对其他获取到读锁的线程是不可见的。

3. 读写锁操作

  1. 读写锁:对于只读的时候, 不需要加锁,但是, 只要和写混合, 或者是单纯的写都需要加锁. 防止数据的错误.
/**
 * 读写锁:
 * 对于只读的时候, 不需要加锁.
 * 但是, 只要和写混合, 或者是单纯的写都需要加锁. 防止数据的错误.
 */
public class ReadWriteLockDemo1 {
    private static final ReadWriteLock lock = new ReentrantReadWriteLock();

    private static final Lock readLock = lock.readLock();

    private static final Lock writeLock = lock.writeLock();

    public static void main(String[] args) throws InterruptedException {        
    	IntStream.rangeClosed(0, 5).forEach(item -> {
            new Thread(ReadWriteLockDemo1::write).start();
        });

        TimeUnit.SECONDS.sleep(2);

        IntStream.rangeClosed(0, 5).forEach(item -> {            
        new Thread(ReadWriteLockDemo1::read).start();
        });
    }
    
    private static void write() {
        try {
            System.out.println(Thread.currentThread().getName() + "write in");
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + "write work");
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {            
        	e.printStackTrace();
        } finally {            
        	writeLock.unlock();
        }
        
        System.out.println(Thread.currentThread().getName() + "write end");
    }
    
    private static void read() {
        try {
            System.out.println(Thread.currentThread().getName() + "read in");
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "read work");
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {            
        	e.printStackTrace();
        } finally {            
        	readLock.unlock();
        }
        
        System.out.println(Thread.currentThread().getName() + "read end");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值