接口 Lock

java.util.concurrent.locks
接口 Lock

所有已知实现类:
ReentrantLock,
ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock

public interface Lock

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

锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如
ReadWriteLock 的读取锁。

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

虽然 synchronized 方法和语句的范围机制使得使用监视器锁编程方便了很多,而且还帮助避免了很多涉及到锁的常见编程错误,但有时也需要以更为灵活的方式使用锁。例如,某些遍历并发访问的数据结果的算法要求使用 "hand-over-hand" 或 "chain locking":获取节点 A 的锁,然后再获取节点 B 的锁,然后释放 A 并获取 C,然后释放 B 并获取 D,依此类推。Lock 接口的实现允许锁在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁,从而支持使用这种技术。

随着灵活性的增加,也带来了更多的责任。不使用块结构锁就失去了使用 synchronized 方法和语句时会出现的锁自动释放功能。在大多数情况下,应该使用以下语句:

     Lock l = ...;
     l.lock();
     try {
         // access the resource protected by this lock
     } finally {
         l.unlock();
     }
 

锁定和取消锁定出现在不同作用范围中时,必须谨慎地确保保持锁定时所执行的所有代码用 try-finally 或 try-catch 加以保护,以确保在必要时释放锁。

Lock 实现提供了使用 synchronized 方法和语句所没有的其他功能,包括提供了一个非块结构的获取锁尝试 (tryLock())、一个获取可中断锁的尝试 (lockInterruptibly())
和一个获取超时失效锁的尝试 (tryLock(long, TimeUnit))。

Lock 类还可以提供与隐式监视器锁完全不同的行为和语义,如保证排序、非重入用法或死锁检测。如果某个实现提供了这样特殊的语义,则该实现必须对这些语义加以记录。

注意,Lock 实例只是普通的对象,其本身可以在 synchronized 语句中作为目标使用。获取
Lock
实例的监视器锁与调用该实例的任何 lock() 方法没有特别的关系。为了避免混淆,建议除了在其自身的实现中之外,决不要以这种方式使用 Lock 实例。

除非另有说明,否则为任何参数传递 null 值都将导致抛出 NullPointerException

内存同步

所有 Lock 实现都必须 实施与内置监视器锁提供的相同内存同步语义,如 The Java Language Specification, Third Edition (17.4 Memory Model) 中所描述的:

  • 成功的 lock 操作与成功的 Lock 操作具有同样的内存同步效应。
  • 成功的 unlock 操作与成功的 Unlock 操作具有同样的内存同步效应。

不成功的锁定与取消锁定操作以及重入锁定/取消锁定操作都不需要任何内存同步效果。

实现注意事项

三种形式的锁获取(可中断、不可中断和定时)在其性能特征、排序保证或其他实现质量上可能会有所不同。而且,对于给定的 Lock 类,可能没有中断正在进行的 锁获取的能力。因此,并不要求实现为所有三种形式的锁获取定义相同的保证或语义,也不要求其支持中断正在进行的锁获取。实现必需清楚地对每个锁定方法所提供的语义和保证进行记录。还必须遵守此接口中定义的中断语义,以便为锁获取中断提供支持:完全支持中断,或仅在进入方法时支持中断。

由于中断通常意味着取消,而通常又很少进行中断检查,因此,相对于普通方法返回而言,实现可能更喜欢响应某个中断。即使出现在另一个操作后的中断可能会释放线程锁时也是如此。实现应记录此行为。

从以下版本开始:
1.5
另请参见:
ReentrantLock,
Condition, ReadWriteLock

方法摘要
 void lock()

          获取锁。
 void lockInterruptibly()

          如果当前线程未被中断,则获取锁。
 Condition newCondition()

          返回绑定到此 Lock 实例的新 Condition 实例。
 boolean tryLock()

          仅在调用时锁为空闲状态才获取该锁。
 boolean tryLock(long time,
TimeUnit unit)

          如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
 void unlock()

          释放锁。

 

方法详细信息

lock

void lock()
获取锁。

如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。

实现注意事项

Lock 实现可能能够检测到锁的错误使用,比如会导致死锁的调用,在那种环境下还可能抛出一个 (unchecked) 异常。Lock 实现必须对环境和异常类型进行记录。


lockInterruptibly

void lockInterruptibly()
                       throws InterruptedException
如果当前线程未被中断,则获取锁。

如果锁可用,则获取锁,并立即返回。

如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:

  • 锁由当前线程获得;或者
  • 其他某个线程中断当前线程,并且支持对锁获取的中断。

如果当前线程:

  • 在进入此方法时已经设置了该线程的中断状态;或者
  • 在获取锁时被中断,并且支持对锁获取的中断,

则将抛出 InterruptedException,并清除当前线程的已中断状态。

实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

抛出:
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)。

tryLock

boolean tryLock()
仅在调用时锁为空闲状态才获取该锁。

如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false

此方法的典型使用语句如下:

      Lock lock = ...;
      if (lock.tryLock()) {
          try {
              // manipulate protected state
          } finally {
              lock.unlock();
          }
      } else {
          // perform alternative actions
      }
 

此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。

返回:
如果获取了锁,则返回 true;否则返回 false

tryLock

boolean tryLock(long time,
                TimeUnit unit)
                throws InterruptedException
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。

如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:

  • 锁由当前线程获得;或者
  • 其他某个线程中断当前线程,并且支持对锁获取的中断;或者
  • 已超过指定的等待时间

如果获得了锁,则返回值 true

如果当前线程:

  • 在进入此方法时已经设置了该线程的中断状态;或者
  • 在获取锁时被中断,并且支持对锁获取的中断,

则将抛出 InterruptedException,并会清除当前线程的已中断状态。

如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断,或者报告出现超时情况。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

参数:
time - 等待锁的最长时间
unit - time 参数的时间单位
返回:
如果获得了锁,则返回 true;如果在获取锁前超过了等待时间,则返回 false
抛出:
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)

unlock

void unlock()
释放锁。

实现注意事项

Lock 实现通常对哪个线程可以释放锁施加了限制(通常只有锁的保持者可以释放它),如果违背了这个限制,可能会抛出(未经检查的)异常。该
Lock 实现必须对所有限制和异常类型进行记录。


newCondition

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

在等待条件前,锁必须由当前线程保持。调用 Condition.await() 将在等待前以原子方式释放锁,并在等待返回前重新获取锁。

实现注意事项

Condition 实例的具体操作依赖于
Lock 实现,并且该实现必须对此加以记录。

返回:
用于此 Lock 实例的新 Condition 实例
抛出:
UnsupportedOperationException - 如果此
Lock 实现不支持条件
时间: 2025-01-27 07:43:45

接口 Lock的相关文章

测试并发应用 (一)监控Lock接口

声明:本文是< Java 7 Concurrency Cookbook>的第八章, 作者: Javier Fernández González 译者:郑玉婷   校对:方腾飞 监控Lock接口 Lock 接口是Java 并发 API提供的最基本的机制来同步代码块.它允许定义临界区.临界区是代码块可以共享资源,但是不能被多个线程同时执行.此机制是通过Lock 接口和 ReentrantLock 类实现的. 在这个指南,你将学习从Lock对象可以获取的信息和如何获取这些信息. 准备 指南中的例子是

Java并发编程相关面试问题

基础概念 1.什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)? 原子操作(atomic operation)意为"不可被中断的一个或一系列操作" .处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作. 在Java中可以通过锁和循环CAS的方式来实现原子操作. CAS操作--Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作. 原子操作是

Java 编程要点之并发(Concurrency)详解

本文详细介绍了 Java 并发(Concurrency)的基础用法和原理. 计算机用户想当然地认为他们的系统在一个时间可以做多件事.他们认为,他们可以工作在一个字处理器,而其他应用程序在下载文件,管理打印队列和音频流.即使是单一的应用程序通常也是被期望在一个时间来做多件事.例如,音频流应用程序必须同时读取数字音频,解压,管理播放,并更新显示.即使字处理器应该随时准备响应键盘和鼠标事件,不管多么繁忙,它总是能格式化文本或更新显示.可以做这样的事情的软件称为并发软件(concurrent softw

Java多线程与并发库高级应用

想快速精通多线程?看这里  http://blog.chinaunix.net/uid-540802-id-4431193.html 什么是线程         线程,是程序执行流的最小单元.是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源,一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行.在单个程序中同时运行多个线程完成不同的工作,称为多线程.当自己想

MySQL · 引擎特性 · 初识 MySQL GIS 及 InnoDB R-TREE

一直以来MySQL在GIS上的功能支持都比较弱,并且仅有MyISAM引擎支持.很高兴的看到MySQL5.7将这个短板补上了,实现了InnoDB引擎的GIS支持,现在对GIS数据可以支持完整的MVCC和事务特性.在MySQL5.7版本里,针对GIS特性主要做了几点改进: InnoDB支持Spatial Index,可以对空间数据类型建立索引 更丰富的功能,支持计算两点之间的球面距离函数st_distance_sphere,新增支持GeoHash和GeoJSON: 基于Boost.Geometry库

JAVA多线程和并发基础面试问答

原文链接  译文连接 作者:Pankaj  译者:郑旭东  校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的

Java多线程和并发基础面试题(问答形式)_java

本文帮助大家掌握Java多线程基础知识来对应日后碰到的问题,具体内容如下 一.Java多线程面试问题 1. 进程和线程之间有什么不同?一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进程.线程可以被称为轻量级进程.线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源. 2. 多线程编程的好处是什么?在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU

JAVA多线程和并发基础面试问答(翻译)_java

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进程.线程可以被称为轻量级进程.线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源. 2. 多线程编程的好处是什么? 在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态.多个线程共享堆内存(heap

银行取款[多线程]{使用重入锁Lock接口ReentrantLock锁确保线程同步}

经典例子:老婆(朱丽叶)老公(罗密欧),使用银行卡和存折,或者网银等,同时对同一账户操作的安全问题.  此处用多线程实现,同时取款的模拟实现,使用使用Lock接口ReentrantLock锁确保线程同步,查看取款安全隐患问题,代码如下: -----------------------------------------------------------------------------------------------------------------------------------