标签:lock unsafe 命令 修改 占用 system art getname second
公平锁,非公平锁
公平锁:非常公平,不能插队,必须先来后到
//参数写为true,就表示公平锁(不写默认就是非公平锁)
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
非公平锁:非常不公平,允许插队,可以改变顺序(lock,synchronized默认都是非公平锁)
public ReentrantLock() {
sync = new NonfairSync();
}
可重入锁
简单理解就是:锁里面还有一个锁。
特性:就是一个线程执行可重入锁后,释放全部锁的时候,另一个线程才能继续执行这个可重入锁。
加上A锁里面还有一把B锁。
线程甲执行完A,线程乙还不能执行A,因为A里面还有一把B锁。
甲执行完B锁就会释放B锁,然后再释放A锁,这时乙才能执行(使用lock这个过程特别明显)
通过Synchronized 锁实现
public class LockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sms();
},"A").start();
new Thread(()->{
phone.sms();
},"B").start();
}
}
class Phone{
public synchronized void sms(){
System.out.println(Thread.currentThread().getName()+"=> sms");
call();// 这里也有一把锁
}
public synchronized void call(){
System.out.println(Thread.currentThread().getName()+"=> call");
}
}
A=> sms
A=> call
B=> sms
B=> call
Lock 锁实现可重入锁
public class LockDemo {
public static void main(String[] args) {
Phone2 phone2 = new Phone2();
new Thread(()->{
phone2.sms();
},"A").start();
new Thread(()->{
phone2.sms();
},"B").start();
}
}
class Phone2 {
Lock lock = new ReentrantLock();
public void sms() {
lock.lock();//细节:这个两把锁,两个钥匙
// lock 锁必须配对,否则就是死锁在里面
try {
System.out.println(Thread.currentThread().getName() + "=>sms");
call();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "=>call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
A=>sms
A=>call
B=>sms
B=>call
自旋锁
何谓自旋锁?它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名
自旋锁会不断的尝试,直到成功为主。
其实在Unsafe类中就有自旋锁的使用,下面的源码通过CAS和while循环就实现了自旋锁。
示例:自定义实现自旋锁(自旋锁是通过CAS和while循环实现的)
public class SpinlockDemo {
//使用原子类通过CAS实现自旋锁
// 默认
// int 0
//thread null
AtomicReference<Thread> atomicReference=new AtomicReference<>();
//加锁
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"===> mylock");
//自旋锁 当有一个线程A调用该方法,就将原始值null改为A thread,修改成功就结束自旋
while (!atomicReference.compareAndSet(null,thread)){
//System.out.println(Thread.currentThread().getName()+" ==> 自旋中~");
}
}
//解锁
public void myUnlock(){
Thread thread=Thread.currentThread();
System.out.println(thread.getName()+"===> myUnlock");
atomicReference.compareAndSet(thread,null);
}
}
public class TestSpinLock {
public static void main(String[] args) throws InterruptedException {
//使用CAS实现自旋锁
SpinlockDemo spinlockDemo=new SpinlockDemo();
new Thread(()->{
spinlockDemo.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
spinlockDemo.myUnlock();
}
},"t1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
spinlockDemo.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
spinlockDemo.myUnlock();
}
},"t2").start();
}
}
t1===> mylock
t2===> mylock
t1===> myUnlock
t2===> myUnlock
//从上面的结果我们看到,t1拿到锁后,一直在自旋,直到thread不等于空结束自旋。t2才能拿到锁,然后自旋,最后解锁
死锁
简单理解:A:先交货再给;B:先给钱再交货
死锁示例
public class DeadLock {
public static void main(String[] args) {
String lockA= "lockA";
String lockB= "lockB";
new Thread(new Mythread(lockA,lockB),"t1").start();
new Thread(new Mythread(lockB,lockA),"t2").start();
}
}
class Mythread implements Runnable{
private String lockA;
private String lockB;
public Mythread(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run() {
synchronized (lockA){
System.out.println(Thread.currentThread().getName()+" lock"+lockA+"===>get"+lockB);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB){
System.out.println(Thread.currentThread().getName()+" lock"+lockB+"===>get"+lockA);
}
}
}
}
如何排查死锁
运行程序造成死锁后,打开idea Terminal控制台。
输入使用 jps 定位进程号(jdk 目录 bin 下 :有一个 jps)
命令: jps -l
查看所有进程号
使用 jstack
进程进程号找到死锁信息
参考教程:https://www.kuangstudy.com/
标签:lock unsafe 命令 修改 占用 system art getname second
原文地址:https://www.cnblogs.com/lanxinren/p/14724629.html