显示锁和隐式锁的区别,还有线程不安全的解决方法

线程不安全

解决方案1:同步代码块

格式: synchronized(锁对象){} //java中任何对象都可以作为锁对象加上锁标记
100个对象要上同个锁才能合理

解决方案2:同步方法(还需了解)

public synchronized boolean sale(){
//不是静态就是this 是静态就是类名.class
}

解决方案3:显示锁Lock

同步代码块和同步方法都属于隐式锁
显示锁Lock子类 ReentrantLock()
private Lock lo = new ReentrantLock(); //自己创建一把锁
lo.lock(); //上锁
lo.unlock(); //解锁

显示锁和隐式锁的区别

java中隐式锁:synchronized;显示锁:lock

1.构成不同

Synchronized:java中的关键字,是由JVM来维护的,是JVM层面的锁。
Lock:是jdk5之后出现的具体的类,使用lock是调用对应的API,是API层面的锁。
synchronized的底层是通过monitorenter进行加锁
(底层是通过monitor对象来完成的,其中的wait/notify等方法也是依赖于monitor对象的。
只有在同步代码块或者是同步方法中才可以调用wait/notify等方法的。因为只有在同步块或者是同步方法中,JVM才会调用monitory对象的)
通过monitorenter来初始化和获取锁,monitorexit来释放锁的。

而lock是通过调用对应的API方法来获取锁和释放锁的。

2.使用方式不同

所谓的显示和隐式就是在使用的时候,使用者要不要手动写代码去获取锁和释放锁的操作。
我们大家都知道,在使用synchronized关键字的时候,我们使用者根本不用写其他的代码,然后程序就能够获取锁和释放锁了。
那是因为当sync代码块执行完成之后,系统会自动的让程序释放占用的锁。Sync是由系统维护的,如果非逻辑问题的话话,是不会出现死锁的。

在使用lock的时候,我们使用者需要手动的获取和释放锁。如果没有释放锁,就有可能导致出现死锁的现象。
手动获取锁方法:lock.lock()。释放锁:unlock方法。需要配合tyr/finaly语句块来完成

3.等待是否可以中断

Synchronized是不可中断的,除非抛出异常或正常运行完成

Lock是可以中断的。
中断方式:
(1)、tryLock
boolean tryLock()
仅在调用时锁为空闲状态才获取该锁。
如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。
返回值:如果获取了锁,则返回 true;否则返回 false。

(1.1)、tryLock
boolean tryLock(long time,
TimeUnit unit)
throws InterruptedException
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:
锁由当前线程获得;或者
其他某个线程中断当前线程,并且支持对锁获取的中断;或者
已超过指定的等待时间
如果获得了锁,则返回值 true。

如果当前线程:在进入此方法时已经设置了该线程的中断状态;或者
在获取锁时被中断,并且支持对锁获取的中断,
则将抛出 InterruptedException,并会清除当前线程的已中断状态。
如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

实现注意事项:
在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录
相对于普通方法返回而言,实现可能更喜欢响应某个中断,或者报告出现超时情况。
Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

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

(2)、调用lockInterruptibly()放到代码块中,然后调用interrupt()方法可以中断

4.加锁的时候是否可以公平

Locks 是公平锁
Lock lo = new ReentrantLock(true); //公平锁 就是谁先来谁得到这个锁
显示锁lo:fair参数为true,就表示是公平锁,默认(不填)是false.

Synchronized是不公平锁
即排队抢锁,同时抢锁都是不公平锁。

5.锁绑定多个条件来condition

Synchronized:没有,要么随机唤醒一个线程;要么是唤醒所有等待的线程。

Lock:用来实现分组唤醒需要唤醒的线程,可以精确的唤醒,而不是像synchronized那样,不能精确唤醒线程。

6.从性能比较在这里插入图片描述

7.从使用锁的方式比较在这里插入图片描述

一些内容转载自https://www.cnblogs.com/kaigejava/p/12710602.html
https://blog.51cto.com/2839840/2326202

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值