【并发编程】Lock锁及其常见子类

Lock锁及其常见子类

Lock

public interface Lock {

常用方法

// 获取锁
void lock();
// 释放锁
void unlock();
// 可以被中断的锁
void lockInterruptibly() throws InterruptedException;
// 尝试获取锁并返回当前锁的获取情况。
boolean tryLock(); 
// 尝试获取一段时间的锁并返回当前锁的情况
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 
// 获取监听器 三个主要方法await()、signal()、signalAll()
Condition newCondition(); 

Lock和synchronized的区别?

  • synchronized是java的关键字,Lock是一个接口
  • synchronized无法判断锁的状态,Lock可以判断是否获取到锁
  • synchronized会自动释放锁,Lock必须手动释放锁
  • synchronized线程1(获得锁,阻塞)线程2(等待,继续等待),Lock有可能插队
  • synchronized可重入锁、不可中断、非公平锁,Lock可重入锁、可中断、可以设置公平/非公平
  • synchronize适合锁少量代码的同步问题,Lock适合锁大量代码的同步问题

ReentrantLock

public class ReentrantLock implements Lock, java.io.Serializable {

可重入锁,可以用来替换synchronized

synchronized是独占锁,开锁解锁自动进行。ReentrantLock也是独占锁,开锁解锁通过 lock/unlock 方法手动进行

synchronized是可重入的,ReentrantLock也是可重入的,但是加锁解锁的次数必须要一样

synchronized不可以响应中断,一个线程获取不到锁就一直阻塞着。ReentrantLock则可以响应中断。

ReentrantLock可以实现公平锁机制,通过构造器设置

Lock lock = new ReentrantLock(true)
lock.lock();

tryLock()方法是非公平实现,所以就算是构造了公平的ReentrantLock锁,调用该方法也不能保证公平,如果要遵从公平规则可以使用tryLock(long timeout, TimeUnit unit)

在这里插入图片描述

ReentrantLock的lock()方法就是调用他内部类Sync下的lock(),而lock()中调用的acquire(1)则是继承至 AbstractQueuedSynchronizer

ReentrantReadWriteLock

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {

读写锁,分为读锁和写锁。读锁允许同一时刻被多个读线程访问,写锁是独占锁使用时所有读线程和写线程都会被阻塞。
支持非公平性(默认)和公平的锁获取方式

支持重入,读锁获取后能再次获取读锁,写锁获取之后能够再次获取写锁,同时也能够获取读锁

锁降级,写锁能够降级成为读锁:获取写锁->获取读锁->释放写锁->释放读锁

不支持读锁升级为写锁

读锁其实就是调用的 acquireSharedreleaseShared 共享锁

写锁其实就是调用的 acquirerelease

public static void main(String[] args) {
    ExecutorService executorService = Executors.newFixedThreadPool(20);
    Cache cache = new Cache();
    for (int i = 1; i <= 100; i++) {
        final int temp = i;
        executorService.submit(() -> {
            cache.put(String.valueOf(temp), null);
        });
    }

    for (int i = 1; i <= 100; i++) {
        final int temp = i;
        executorService.submit(() -> {
            cache.get(String.valueOf(temp));
        });
    }
}

static class Cache{
    ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<String, String> map = Maps.newHashMap();

    public void put(String key, String value){
        lock.writeLock().lock();
        System.out.println(Thread.currentThread().getName() + "写线程占用");
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + "写线程释放");
        lock.writeLock().unlock();
    }

    public void get(String key){
        lock.readLock().lock();
        System.out.println(Thread.currentThread().getName() + "读线程占用");
        map.get(key);
        System.out.println(Thread.currentThread().getName() + "读线程释放");
        lock.readLock().unlock();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值