linux怎么查看本机内存大小
288
2022-12-22
java并发之Lock接口的深入讲解
目录Juc中各种各样锁信息synchronized面临缺点Lock接口对比 Lock和tryLock的区别总结
Juc中各种各样锁信息
在java的juc包为我们提供了各种各样的锁信息。如果细心来看其大部分都会实现一个名为LOCK的接口信息本文皆在帮你回顾Lock信息;
通过本文你将了解到如下内容:
1.Lock和synchronized的对比
2.Lock中常见API的总结
synchronized面临缺点
锁的出现主要是为了保证在并发访问共享资源时不出现错。 在java中如果不考虑性能损耗问题,那么对共享的资源信息加上synchrionzed关键字基本就可以解决大多数并发带来的问题,但是也随之带来灵活性和效率上的问题:
效率方面:
1. 此种情况下锁的释放情况较少,很容易到导致一直独占资源而导致性能的下降。
2. 当我们试图获取锁时不能直接指定具体条件
3. 不能中断正在试图获得锁的线程
灵活性:
1. 当获得锁资源后,无法得知是否获得锁信息
2. 仅当程序异常或顺利执行完时才会释放锁信息,缺乏主动释放锁的时机。
不适用的场景
场景1 :
当我们使用synchronized时,假如某线程获取到锁之后由于要等待IO或者其他原因进入阻塞状态,同时未释放锁信息,那么此时其他线程就只能一直等待。所以此时就需要synchronized有一种机制:避免等待的线程一直无期限地等待下去。
场景2 :
在读文件信息形式,不同线程的写操作是相互冲突的。但是读操作并不会导致冲突。如果我们不加考虑的为资源信息加上synchronized关键字,那么当多线程同时操作时,只有一个线程可以获取到资源,其他未获得锁信息的线程只能进入等待状态,从而导致读写效率不高。
Lock接口
Lock接口是对关键字synchronized的补充和扩展,它允许我们可以在线程安全的情况下更加灵活的操作共享资源信息。
常见用法:
Lock最佳实践:
1.lock(),unlock()
一般来说,使用Lock必须在try…catch…块中进行,并且将释放锁的操作放在finally块中进行。这是因为lock并不会像synchronized那样在异常时释放锁,所以必须保证有手动释放的过程,这样才能保证其它线程有获取锁的机会。
// 加锁
lock.lock();
try{
//处理任务
}catch(Exception ex){
}finally{
//释放锁 (锁的释放一般放入到finally块中进行,这样保证了总会对锁信息进行释放)
lock.unlock();
}
2. tryLock() & tryLock(long time, TimeUnit unit)
tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true;如果获取失败(即锁已被其他线程获取),则返回false,也就是说,这个方法无论如何都会http://立即返回即使其无法获取到锁也不会一致等待。
tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false
如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。一般情况下,通过tryLock来获取锁时是这样使用的:
Lock lock = ...;
if(lock.tryLock()) {
try{
//处理任务
}catch(Exception ex){
}finally{
lock.unlock(); //释放锁
}
}else {
//如果不能获取锁,则直接做其他事情
}
3. lockInterruptibly()
lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程 正在等待获取锁,则这个线程能够 响应中断,即中断线程的等待状态。
例如,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。
public void method() throws InterruptedException {
lock.lockInterruptibly();
try {
//.....
}
finally {
lock.unlock();
}
}
当一个线程获取了锁之后,是不会被interrupt()方法中断的。因为interrupt()方法只能中断阻塞过程中的线程而不能中断正在运行过程中的线程。而在 synchronized 中,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去,这也就是我们需要手动释放锁的原因。
给出如下的例子来进行验证:创建两个线程来共同争抢lock锁信息
public class LockInterruptibly implements Runnable {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
LockInterruptibly lockInterruptibly = new LockInterruptibly();
Thread thread0 = new Thread(lockInterruptibly);
Thread thread1 = new Thread(lockInterruptibly);
thread0.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.start();
thread1.interrupt();
}
// 任务执行逻辑
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "尝试获取锁");
try {
lock.lockInterruptibly();
try {
System.out.println(Thread.currentThread().getName() + "获取到了锁");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(TLtrwRWHdJhread.currentThread().getName() + "睡眠期间被中断了");
} finally {
lock.unlock();
SysLtrwRWHdJtem.out.println(Thread.currentThread().getName() + "释放了锁");
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "获得锁期间被中断了");
}
}
}
执行结果:
Thread-0尝试获取锁
Thread-0获取到了锁
Thread-1尝试获取锁
Thread-1获得锁期间被中断了
Thread-0释放了锁
通过结果信息我们可以看出,lockInterruptibly()仅能中断正在等待的线程信息,而无法中断正在运行的线程。
对比 Lock和tryLock的区别
lock和tryLock都可以获取到锁信息,但两者之间还是存在些差异的。 具体如下:
1: lock拿不到锁会一直等待。tryLock是去尝试,拿不到就返回false,拿到返回true。
2: tryLock是可以被打断的,被中断的,lock是不可以。
// 实例代码
public class LockDemo implements Runnable{
static Lock lock1 = new ReentrantLock();
@Override
public void run() {
// 分别演示 lock,trylock区别
// lock1.lock();
lock1.tryLock();
System.out.println("线程 " + Thread.currentThread().getName() + " 获取到锁信息 ");
}
public static void main(String[] args) throws InterruptedException {
LockDemo r1 = new LockDemo();
LockDemo r2 = new LockDemo();
r1.flag = true;
r2.flag = false;
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.sleep(1000);
// 中断
t2.start();
t2.interrupt();
}
}
结果信息:
当执行lock1.lock()时的输出:可以看到lock方法并不能响应中断信息,如果不解锁则会一致持有锁信息!
对于tryLock而言其可以响应中断
总结
本篇对Lock接口中常用到的Api进行了分析和总结,同时分析了Lock接口和synchronized关键之间的关系,希望对你能有所启发.
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~