公平锁
先来先服务,不允许插队
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
复制代码
非公平锁
允许插队,一般默认非公平锁,效率更高
public ReentrantLock() {
sync = new NonfairSync();
}
复制代码
可重入锁
即允许同一个线程多次获取同一把锁
实现:synchronized,ReentrantLock
- 对象A有两个同步方法a,b。
- 当我们进入同步方法a时我们获取了对象A的锁
- 在a中我们调用b则需要再次获得对象A的锁。这是被允许的
public class LockTest {
public static void main(String[] args) {
new Thread(()->{
a();
}).start();
}
public static synchronized void a(){
System.out.println("a");
b();
}
public static synchronized void b(){
System.out.println("b");
}
}
复制代码
自旋锁
- 一个线程A等待对象A的锁时
- 对象A的锁已经被线程B获取了。
- 线程A进入while循环等待而不是sleep
public static void main(String[] args) throws InterruptedException {
myLock myLock=new myLock();
// 线程0 获取锁后休息2秒
new Thread(()->{
myLock.mylock();
try{
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
myLock.myunlock();
}
}).start();
TimeUnit.SECONDS.sleep(1);
//在线程0获取锁休息的时候,线程1不断的自旋等待锁的释放
new Thread(()->{
try{
myLock.mylock();
}finally {
myLock.myunlock();
}
}).start();
}
}
复制代码
class myLock{
private AtomicReference<Thread> atomicReference=new AtomicReference<>();
public void mylock(){
Thread thread=Thread.currentThread();
System.out.println(thread.getName()+"->>mylock");
// 不断循环等待
while(!atomicReference.compareAndSet(null,thread)){};
}
public void myunlock(){
Thread thread=Thread.currentThread();
System.out.println(thread.getName()+"->>myunlock");
// 释放
atomicReference.compareAndSet(thread,null) ;}
}
复制代码
死锁
- 线程A等待锁a,但锁a已经被线程B获取,陷入等待
- 线程B等待锁b,但锁b已经被线程A获取,陷入等待
- 相互等待永无止境
产生死锁的必要条件:
- 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
- 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可抢占:资源不能被抢占,即资源只能被进程在完成任务后自愿释放
- 循环等待:在发生死锁时,必然存在一个进程–资源的环形链。
死锁排查
jps -l 查看进程
jstack 查找死锁
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END