Java如何实现同步锁
1 Synchronized 关键字
- 为了防止共享对象在并发访问时出现错误,Java中提供了“synchronized”关键字。
- 确保共享对象在同一时刻只能被一个线程访问,这种处理机制称为“线程同步”或“线程互斥”。Java中的“线程同步”基于“对象锁”的概念。
- 修饰方法:被“synchronized”关键字修饰的方法称为“同步方法”。
//定义同步方法
public synchronized void method(){
//方法实现
}
- 当一个线程访问对象的同步方法时,被访问对象就处于“锁定”状态,访问该方法的其他线程只能等待,对象中的其他同步方法也不能访问,但非同步方法则可以访问。
- 使用 ”synchronized” 关键字:修饰部分代码,如果只希望同步部分代码行,可以使用“同步块”
//同步块
synchronized(obj){
//被同步的代码块
}
- 同步块的作用与同步方法一样,只是控制范围有所区别。
2 lock
一个接口interface。有下面几种常用的方法:
-
首先lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。由于在前面讲到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。通常使用Lock来进行同步的话,是以下面这种形式去使用的:
-
tryLock():tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
-
tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
tryLock的用法:
-
lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调threadB.interrupt()方法能够中断线程B的等待过程。
-
由于lockInterruptibly()的声明中抛出了异常,所以lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()的方法外声明抛出InterruptedException。
因此lockInterruptibly()一般的使用形式如下: