Lock: 概述

锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问 共享资源(但是有些锁可以允许多个线程并发的访问共享资源,如读写锁)。

Lock与synchronized

Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增了Lock接口(及其相关实现类),它们提供了与synchronized关键字类似的同步功能。

Lock与synchronized关键字比较:Lock使用时需要显示地获取和释放锁,而synchronized块是隐式地获取和释放锁,但是Lock却拥有了锁获取和释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字不具备的同步特性。

Lock接口提供的synchronized关键字不具备的主要特性:

  1. 尝试非阻塞地获取锁
    当前线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
  2. 能被中断地获取锁
    与synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会抛出,同时锁会被释放。
  3. 超时获取锁
    在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取锁,则返回。

synchronized关键字的同步实现参见:Class文件(2): 字节码指令-同步指令

Java中的原子操作

在Java中通过锁和循环CAS来实现原子操作。

JVM中的CAS操作利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止

锁机制保证了只有获得锁的线程才能够操作锁定的内存区域。JVM中实现锁的方式基本上(除了偏向锁)都用了循环CAS,即当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁