锁
什么是死锁?
多个进程在运行过程中因资源争夺而造成的阻塞状态。
比如一个线程A,按照先获得锁a再获得锁b的顺序获得锁,同时又有一个锁B,按照先获得锁b再获得锁a的顺序获得锁。
死锁产生的四个必要条件?
**互斥:**某资源一次只允许一个进程访问,该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
**不可剥夺:**别人已经占有了某项资源,你不能因为自己也要就去抢过来。
**循环等待:**存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。
**请求与保持:**一个进程本身占有资源,同时还有资源未得到满足,正在等待其他进程释放该资源。
解决死锁的几种方式?
破坏 互斥条件
破坏 占有并等待
破坏 不可抢占
预防死锁的几个方法?
01.避免一个线程同时获取多个锁。
02.避免一个线程在锁内占用多个资源,尽量保证每个锁只占用一个资源。
03.尝试使用定时锁
04.对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
死锁解决方案
- 设置锁超时时间、事务超时时间
- 资源排序,对要锁的记录排序,按相同的顺序申请锁
- 使用其他方案代替悲观锁For Update,比如乐观锁、缓存等
如何判断对象加锁
- 在markword里面存值,通过markword来判断对象是否已经加锁
- markword里面存的是线程锁状态状态还有hashcode
lock接口
synchronized是一个关键字,它基于JVM。它有锁升级过程,从偏向锁,轻量级锁,到重量级锁。
Lock是一个接口,它是基于JDK,它实现的主要实现类是ReentrantLock,它的使用也离不开AQS。
等待通知机制
等待/通知机制就是一个【线程A】等待,一个【线程B】通知(线程A可以不用再等待了)。
是指一个线程调用了一个对象 的wait()方法进入了等待状态,而另一个线程B调用了对象的notify()或者notifyAll()方法,线程A收到通知后从对象 O 的wait()方法返回,进而执行后序操作。
实现等待通知机制主要是用:wait()/notify()
方法实现
-
wait()
方法 :wait()方法是使当前执行代码的线程进行等待,该方法用来将当前线程置入“欲执行队列”中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。在调用wait()
方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。 -
notify()
方法:方法notify()也要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁。这两个方法都需要同
synchronized
关键字联用。
ThreadLocal的使用
- ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
- Profiler可以被复用在方法调用耗时统计的功能上,在方法的入口前执行begin()方法,在方法调用后执行end()方法,好处是两个方法的调用不用在一个方法或者类中,比如在AOP(面向方面编程)中,可以在方法调用前的切入点执行begin()方法,而在方法调用后的切入点执行 end()方法,这样依旧可以获得方法的执行耗时。
- ThreadLocal源码理解
- 都是在自己的线程内设置值,获取值,无论开几个线程,只要最后回到这个线程,他还会得到这个值(类似seesion)。