LockInterface

Lock简介以及和synchronized的比较

​ 在锁定操作上,相对于使用synchronized方法和语句快,Lock能获得的更广泛的锁定操作。它们允许更灵活的结构,可能具有完全不同的属性,并且可能支持多个关联的Condition对象。

​ 锁是一种用于控制多个线程对共享资源的访问的工具。通常,锁提供对共享资源的独占访问:一次只有一个线程可以获取锁,并且对共享资源的所有访问都需要首先获取锁。但是,某些锁可能允许并发访问共享资源,例如ReadWriteLock的读锁定。

​ synchronized方法或语句的使用提供了对与每个对象关联的隐式监视器锁的访问,但强制所有锁获取和释放以块结构方式发生:当获取多个锁时,它们必须是以相反的顺序释放,并且所有锁必须在获取它们的相同词法范围内释放。

​ 虽然synchronized方法和语句块的作用域机制使得使用锁进行编程变得更加容易,并且有助于避免许多涉及锁的常见编程错误,但有时需要更灵活地使用锁的办法。例如,用于并发遍历访问的数据结构的一些算法需要锁的交接,或者“链锁定”:你获得节点A的锁,然后是节点B,然后释放A并获得C,然后释放B并获得D,依此类推。 Lock接口的实现允许使用这种技术,允许在不同的范围内获取和释放锁,并允许以任何顺序获取和释放多个锁。

​ 这种增加的灵活性也带来了更多需要注意的地方。因为不再使用synchronized方法和语句块,锁不会自动释放。大多情况下都需要使用以下方式:

​ 缺少块结构锁定会删除使用{@code synchronized}方法和语句发生的锁的自动释放。在大多数情况下,应使用以下习语:

Lock l = ...; 
l.lock(); 
try {
	//访问受此锁保护的资源
} finally {
	l.unlock(); 
}

​ 当锁定和解锁发生在不同的范围内时,必须注意确保在保持锁定时执行的所有代码都受try-finally或try-catch保护,以确保在必要时释放锁定。

​ 相比于synchronized方法和语句块,Lock提供了更多的的附加功能,通过提供获取锁的非阻塞尝试——ryLock,尝试获取可以中断的锁——lockInterruptibly,以及尝试获取可能超时的锁——tryLock(long,TimeUnit)。

​ 另外,Lock类还有一些不同的行为和语义,例如保证排序,非重入使用或死锁检测。

​ 需要注意的是,Lock的实例只是普通对象,可以在synchronized语句中用作目标,即synchronized(lock),这种用法和lock的锁定没有联系。为避免混淆,建议您不要以这种方式使用Lock实例,除非在他们自己的实现中。

内存同步

​ TODO

注意事项

​ 三种形式的锁的获取(可中断,不可中断和定时)可能在性能特征、排序保证或其他质量方面有所不同。在特定的锁的实现类中,可能无法终端ongoing状态的锁。因此,不需要实现为所有三种形式的锁获取定义完全相同的保证或语义,也不需要支持正在进行的锁获取的中断。

​ 需要一种实现来清楚地记录每种锁定方法提供的语义和保证。它还必须遵守此接口中定义的中断语义,以支持锁获取的中断:完全或仅在方法入口上。

​ 由于中断通常意味着取消,并且中断检查通常不常见,因此实现可能有利于响应正常方法返回的中断。即使可以显示在另一个操作可能已取消阻塞线程之后发生中断,也是如此。实现应记录此行为。

接口方法

方法列表

void lock();
  • 获取锁。

  • 如果锁定不可用,则当前线程不再参与线程调度,并且在获取锁定之前处于休眠状态。

  • 使用方式:

void lockInterruptibly() throws InterruptedException;
  • 获取锁,除非线程被中断。
    • 如果锁可用,立即返回
    • 如果锁定不可用,则当前线程不再参与线程调度,并且在获取锁定之前处于休眠状态,除非发生以下事情:
      • 锁被当前线程获取。
      • 或者当前线程被其他线程中断,并且锁的获取支持中断。
boolean tryLock();
  • 锁空闲则获取锁:
    • 锁可用,返回true
    • 锁不可用,返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
  • 获取锁,在给定时间内,在线程未被中断时。

    • 可以获取:立即返回true

    • 不可获取:进入禁用调度状态,休眠直到以下事情发生:

      1. 获取到锁
      2. 被中断
      3. 时间到

      时间到则返回false

void unlock();
  • 释放锁
Condition newCondition();
  • returns a new Condition instance that is bound to this lock instance.

几种获取锁的方法的比较

  • Lock() 拿不到lock就不罢休,不然线程就一直block。 比较无赖的做法。
  • tryLock() 马上返回,拿到lock就返回true,不然返回false。 比较潇洒的做法。
  • 带时间限制的tryLock 比较聪明的做法,相较于tryLock()——支持中断
  • lockInterruptibly() 相较于lock(),支持中断

使用方式

  • lock():
Lock l = ...; 
l.lock(); 
try {
	//访问受此锁保护的资源
} finally {
	l.unlock(); 
}
  • tryLock():
Lock lock = ...;
if(lock.tryLock()) {
     try{
         //处理任务
     }catch(Exception ex){
         
     }finally{
         lock.unlock();   //释放锁
     } 
}else {
    //如果不能获取锁,则直接做其他事情
}
  • lockInterruptibly():
public void method() throws InterruptedException {
    lock.lockInterruptibly();
    try {  
     //.....
    }
    finally {
        lock.unlock();
    }  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值