16.各种锁
各种锁
1、公平锁,非公平锁
公平锁:非常公平,不能插队
非公平锁:非常不公平,可以插队(默认都是非公平)
//非公平锁
ReentrantLock reentrantLock = new ReentrantLock();
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
//公平锁
ReentrantLock reentrantLock = new ReentrantLock(true);
2、可重入锁
可重入锁(递归锁)
Synchronized版
public class SyncDemo {
public static void main(String[] args) {
new Thread(() -> {
Phone phone = new Phone();
phone.sms();
},"A" ).start();
new Thread(() -> {
Phone phone = new Phone();
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");
}
}
Lock版
public class LockDemo {
public static void main(String[] args) {
Phone1 phone = new Phone1();
new Thread(() -> {
phone.sms();
}, "A").start();
new Thread(() -> {
phone.sms();
}, "B").start();
}
}
//
class Phone1 {
ReentrantLock lock = new ReentrantLock();
public void sms() {
lock.lock();//lock和unlock必须成对出现,有加锁就必须有解锁,否则死锁
try {
System.out.println(Thread.currentThread().getName() + " sms");
call();//这里也有锁
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
3、自旋锁
自写自旋锁
/*
* 自定义自旋锁
* */
public class MyLock {
AtomicReference<Thread> reference = new AtomicReference<>();
//加锁
public void myLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + " mylock");
while (!reference.compareAndSet(null, thread)) {
}
}
//解锁
public void myUnLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + " myunlock");
reference.compareAndSet(thread, null);
}
}
测试
public class MyLockTest {
public static void main(String[] args) throws InterruptedException {
MyLock lock = new MyLock();
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);//保证A先获取到锁
new Thread(()->{
lock.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.myUnLock();
}
},"B").start();
}
}
总结:A先拿到锁,执行完,解锁,B才能拿到锁
4、死锁
死锁代码
public class DeadLock implements Runnable {
private String a;
private String b;
public DeadLock(String a, String b) {
this.a = a;
this.b = b;
}
@Override
public void run() {
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "持有锁" + a + ",要去获取锁" + b);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "持有锁" + b + ",要去获取锁" + a);
}
}
}
}
测试
//程序会一直卡着,死锁
//T1持有锁lockA,要去获取锁lockB
//T2持有锁lockB,要去获取锁lockA
public class DeadLockTest {
public static void main(String[] args) {
new Thread(new DeadLock("lockA", "lockB"), "T1").start();
new Thread(new DeadLock("lockB", "lockA"), "T2").start();
}
}
解决问题
-
jps -l定位进程号PS D:\tools\juc> jps -l 11168 sun.tools.jps.Jps 6784 org.jetbrains.idea.maven.server.RemoteMavenServer36 832 lock.deadlock.DeadLockTest 4316 4748 org.jetbrains.jps.cmdline.Launcher PS D:\tools\juc> -
jstack 进程号查看进程信息发现:互相持有对方的锁
"T2": at lock.deadlock.DeadLock.run(DeadLock.java:24) - waiting to lock <0x000000076b8db678> (a java.lang.String) - locked <0x000000076b8db6b0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748) "T1": at lock.deadlock.DeadLock.run(DeadLock.java:24) - waiting to lock <0x000000076b8db6b0> (a java.lang.String) - locked <0x000000076b8db678> (a java.lang.String) at java.lang.Thread.run(Thread.java:748)

浙公网安备 33010602011771号