lock和synchronized的区别
lock和synchronized的区别
一直以来java有很多的相似关键字或相似意义的字,不是很好区别和掌握,下边来说下这两个单词在Java中的基本概念和应用,我这个也是收百家之长来汇总的。
相同点
synchronized和lock都是锁的意思,都是为了线程安全性,
应用合理性和运行效率的。
可以简单理解lock比前置更加优秀和合理,是前者
的优化版。
不同点
主要还是来说说其不同点。
- 一 synchronized在Java中是关键字,有其语言的内置性。 lock则不是java的关键字,它是Java的一个接口类。
- 二 被synchronized修饰的代码块会自动释放锁,而lock则需要手动的释放。
拓展:lock如果没有手动释放锁标记,就有可能出现死锁的现象。
什么是死锁:
是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
死锁的四个必要条件:
1 互斥条件:一个资源每次只能被一个进程使用;
2 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
3 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺;
4 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系;
*synchronized释放锁的两种时机:
1 获取锁的线程执行完代码块,释放对锁的占有。
2 线程发生异常,JVM会让线程自动释放锁。
*lock释放锁:
ReentrantLock加锁(lock())、释放锁(unlock())
三
**
解释说明:
**
有了synchronized关键字,为什么还需要lock这个接口类呢?
synchronized的不足:
1 如果获取锁的线程等待被执行的代码块是被阻塞了(调用了sleep方法/等待IO或其它原因),但是没有释放锁,那么这个线程只能等着代码块被执行完,这样在效率上和用户体验上都是很差的。
2 还有就是多线程写文章时,读操作和写操作会发生冲突现象,写操作和写操作也会发生冲突现象,但是读操作和读操作是不会发生冲突现象的,而你用了synchronized锁来实现同步的话两个读操作也会发生冲突,这样是不合理的。
为了解决这两种或者其它的有关问题就可以使用lock来实现。
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 实现不支持条件
链接: https://mp.csdn.net/mdeditor#(https://mp.csdn.net).