Lock接口

Lock接口

Lock不是Java中的关键字而是 java.util.concurrent.locks 包中的一个接口。下面我们简单介绍一下Lock接口。

 

一、Lock接口简介

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。

Lock相对于synchronized关键字而言更加灵活,你可以自由得选择我你想要加锁的地方。当然更高的自由度也带来更多的责任。

 

Lock接口有6个方法:

 

方法名称 描述
void lock()  获取锁,调用该方法当前线程将会获取锁,当锁获得后,从该方法返回
void lockInterruptibly()  如果当前线程未被中断,则获取锁,可以响应中断

Condition newCondition()  
获取等待通知组件,该组件和当前的锁绑定,当前线程 只有获得了锁,才能调用该组件的wait()方法,而调用后,当前线程将 释放锁
boolean tryLock() 

仅在调用时锁为空闲状态才获取该锁,可以响应中断

尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回 true,否则返回false

boolean tryLock(long time, TimeUnit unit) 

超时的获取锁,当前线程在以下3种情况下会返回:

1 当前线程在超时时间内获得了锁

2 当前线程在超时时间内被中断

3超时时间结束,返回false

void unlock()  释放锁  


void lock()   :获取锁
    是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。在前面已经讲到,如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁


void lockInterruptibly()  : 如果当前线程未被中断,则获取锁,可以响应中断   
    方法比较特殊,当通过这个方法去获取锁时,如果线程 正在等待获取锁,则这个线程能够 响应中断,即中断线程的等待状态。例如,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程


Condition newCondition()   : 返回绑定到此 Lock 实例的新 Condition 实例  


boolean tryLock()   :仅在调用时锁为空闲状态才获取该锁,可以响应中断  
     是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true;如果获取失败(即锁已被其他线程获取),则返回false,也就是说,这个方法无论如何都会立即返回(在拿不到锁时不会一直在那等待)


boolean tryLock(long time, TimeUnit unit)   :如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁
    方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false,同时可以响应中断。如果一开始拿到锁或者在等待期间内拿到了锁,则返回true


void unlock()  :释放锁  

范代码

Lock lock = new ReentrantLock();
    // 获取锁
    lock.lock();
    try {
    
        // 访问此锁保护的资源
    } finally {
        // 释放锁
        lock.unlock();
       
    }

Lock的实现类 ReentrantLock

Lock接口有三个实现类分别是ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock。后面两个是内部类。

ReentrantLock,即 可重入锁。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法

第一个ReentrantLock,在我们平常使用中更为频繁

ReentrantLock是一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

ReentrantLock的构造方法接受一个可选的公平 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。也就是说这里可以设置锁的类型为公平锁还是非公平锁。但是,需要注意的是公平锁的情况下,也不能完全确保公平,它总是趋向公平的情况。

如:Lock lock = new ReentrantLock();

 

实列:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyLockText {

    Lock lock = new ReentrantLock();

    public void lock(String name) {
        // 获取锁
        lock.lock();
        try {
            System.out.println(name + " get the lock");
            // 访问此锁保护的资源
        } finally {
            // 释放锁
            lock.unlock();
            System.out.println(name + " release the lock");
        }
    }

    public static void main(String[] args) {
        MyLockText lt = new MyLockText();
        new Thread(() -> lt.lock("1234")).start();
        new Thread(() -> lt.lock("5678")).start();
    }
}

结果:

1234 get the lock
1234 release the lock
5678 get the lock
5678 release the lock

 

ReadWriteLock 接口只有两个方法:

//返回用于读取操作的锁  
Lock readLock()   
//返回用于写入操作的锁  
Lock writeLock() 

ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持,而写入锁是独占的。

posted on 2020-08-13 18:19  shumeigang  阅读(175)  评论(0)    收藏  举报

导航