java 可重入锁
Posted 偶像java练习生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 可重入锁相关的知识,希望对你有一定的参考价值。
1.公平锁,非公平锁
公平锁:非常公平,不能插队,必须先来后到!
非公平锁:非常不公平,可以插队,例子:一个线程3s 执行完,一个线程3h 执行完,先让3s 的执行,需要插队!
Lock lock = new ReentrantLock();
public ReentrantLock()
sync = new NonfairSync();
ReentranLock 默认是非公平锁
但是可以通过他的构造方法改变为公平锁: 如下
Lock lock = new ReentrantLock(true);
public ReentrantLock(boolean fair)
sync = fair ? new FairSync() : new NonfairSync();
synchronized 锁也是非公平锁,所有的锁默认都是非公平锁,保证我们一个效率问题。
2. 可重入锁
所有的锁都是可重入锁,拿到外面的锁之后,就可以拿到里面的锁,自动获得
代码如下:
package com.lock;
//Synchronized
public class Demo01
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");
输出结果:
Asms
Acall
Bsms
Bcall
A 拿到锁后先执行完毕,再B 执行
下面是LOCK 版的:
package com.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo02
public static void main(String[] args)
Phone phone = new Phone();
new Thread(()->
phone.sms();
,"A").start();
new Thread(()->
phone.sms();
,"B").start();
class Phone2
Lock lock = new ReentrantLock();
public synchronized void sms()
lock.lock();//细节问题:lock.lock 是拿的两把锁,lock.lock;,lock.unlock
lock.lock()
//lock 锁必须配对,否则就会死在里面
try
System.out.println(Thread.currentThread().getName()+"sms");
call();//这里面也有锁
catch (Exception e)
e.printStackTrace();
finally
lock.unlock();
lock.unlock();
public synchronized void call()
lock.lock();
try
System.out.println(Thread.currentThread().getName()+"call");
catch (Exception e)
e.printStackTrace();
finally
lock.unlock();
输出结果:
Asms
Acall
Bsms
Bcall
3.自旋锁
spinlock
自旋锁:不断的去尝试,直到成功为止!
public final int getAndAddInt(Object var1, long var2, int var4)
int var5;
do
var5 = this.getIntVolatile(var1, var2);
while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
我们来自定义下自旋锁:
package com.lock;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class TestSpinLock
public static void main(String[] args) throws InterruptedException
// ReentrantLock reentrantLock = new ReentrantLock();
// reentrantLock.lock();
// reentrantLock.unlock();
//底层使用的自旋锁
SpinLockDemo lock = new SpinLockDemo();
new Thread(()->
try
lock.myLock();
TimeUnit.SECONDS.sleep(3);
catch (Exception e)
e.printStackTrace();
finally
lock.myUnLock();
,"T1").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->
try
lock.myLock();
TimeUnit.SECONDS.sleep(1);
catch (Exception e)
e.printStackTrace();
finally
lock.myUnLock();
,"T2").start();
lock.myLock();
lock.myUnLock();
输出结果:
T1===> mylock
main===> mylock
T2===> mylock
T1==>myUnlock
T2==>myUnlock
main==>myUnlock
T1 解锁后T2 才能解锁,T1 在自旋,T1 解锁后,T2 解锁
4.死锁
死锁测试,怎么排除死锁:
package com.lock;
import java.util.concurrent.TimeUnit;
public class DeadLockDemo
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 );
输出结果:
T2lock:lockB=>getlockA
T1lock:lockA=>getlockB
程序卡住了
解决程序卡住了的问题
1.使用jps 定位进程号
linux ls-l
而jps 则用jps -l 命令如下:
F:\\workSpace\\AWT>jps -l
2128 sun.tools.jps.Jps
2344 com.lock.DeadLockDemo
8024
15100 org.jetbrains.jps.cmdline.Launcher
可以查看到当前死锁的进程为 2344
- 使用 jstack 进程号 进程号找到死锁问题
使用命令 jstack -2344 显示如下,翻到最底下:
面试或者工作中! 排查问题:
1.进程卡了看上线上有没有异常?
异常: - 使用日志查看
- 使用堆栈,信息
如何解决死锁?
解决死锁产生的条件就可以了!
以上是关于java 可重入锁的主要内容,如果未能解决你的问题,请参考以下文章