一个线程需要 同时获取多把锁,这时就容易发生死锁
如:线程1获取A对象锁, 线程2获取B对象锁; 此时线程1又想获取B对象锁, 线程2又想获取A对象锁; 它们都等着对象释放锁, 此时就称为死锁
public static void main(String[] args) {
final Object A = new Object();
final Object B = new Object();
new Thread(()->{
synchronized (A) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
}
}
}).start();
new Thread(()->{
synchronized (B) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (A) {
}
}
}).start();
}
活锁出现在两个线程互相改变对方的结束条件,谁也无法结束
死锁与活锁的区别
//获取ReentrantLock对象
private ReentrantLock lock = new ReentrantLock();
//加锁
lock.lock();
try {
//需要执行的代码
}finally {
//释放锁
lock.unlock();
}
public class ReentrantTest {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
// 如果有竞争就进入`阻塞队列`, 一直等待着,不能被打断
lock.lock();
try {
System.out.println("entry main...");
m1();
} finally {
lock.unlock();
}
}
private static void m1() {
lock.lock();
try {
System.out.println("entry m1...");
m2();
} finally {
lock.unlock();
}
}
private static void m2() {
System.out.println("entry m2....");
}
}
输出结果:
entry main...
entry m1...
entry m2....
Process finished with exit code 0
使用lock.lockInterruptibly()可以从阻塞队列中打断
public class ReentrantTest {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("t1线程启动...");
try {
// lockInterruptibly()是一个可打断的锁, 如果有锁竞争在进入阻塞队列后,可以通过interrupt进行打断
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("等锁的过程中被打断"); //没有获得锁就被打断跑出的异常
return;
}
try {
System.out.println("t1线程获得了锁");
} finally {
lock.unlock();
}
}, "t1");
// 主线程获得锁(此锁不可打断)
lock.lock();
System.out.println("main线程获得了锁");
// 启动t1线程
t1.start();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt(); //打断t1线程
System.out.println("执行打断");
} finally {
lock.unlock();
}
}
}
输出结果:
main线程获得了锁
t1线程启动...
执行打断
等锁的过程中被打断
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.xc.day1.ReentrantTest.lambda$main$0(ReentrantTest.java:27)
at java.lang.Thread.run(Thread.java:748)
Process finished with exit code 0
使用lock.lock()不可以从阻塞队列中打断, 一直等待别的线程释放锁
public class ReentrantTest {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("t1线程启动...");
lock.lock();
try {
System.out.println("t1线程获得了锁");
} finally {
lock.unlock();
}
}, "t1");
// 主线程获得锁(此锁不可打断)
lock.lock();
System.out.println("main线程获得了锁");
// 启动t1线程
t1.start();
try {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt(); //打断t1线程
System.out.println("main线程执行打断");
} finally {
lock.unlock();
}
}
}
输出结果:
main线程获得了锁
t1线程启动...
main线程执行打断
t1线程获得了锁
Process finished with exit code 0
不设置等待时间, 立即失败
public class ReentrantTest {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("尝试获得锁");
// 此时肯定获取失败, 因为主线程已经获得了锁对象
if (!lock.tryLock()) {
System.out.println("获取立刻失败,返回");
return;
}
try {
System.out.println("获得到锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
System.out.println("获得到锁");
t1.start();
// 主线程2s之后才释放锁
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("释放了锁");
lock.unlock();
}
}
输出结果:
获得到锁
尝试获得锁
获取立刻失败,返回
释放了锁
Process finished with exit code 0
设置等待时间, 超过等待时间还没有获得锁, 失败, 从阻塞队列移除该线程
public class ReentrantTest {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("尝试获得锁");
try {
// 设置等待时间, 超过等待时间 / 被打断, 都会获取锁失败; 退出阻塞队列
if (!lock.tryLock(1, TimeUnit.SECONDS)) {
System.out.println("获取锁超时,返回");
return;
}
} catch (InterruptedException e) {
System.out.println("被打断了, 获取锁失败, 返回");
e.printStackTrace();
return;
}
try {
System.out.println(Thread.currentThread().getName()+"获得到锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
System.out.println(Thread.currentThread().getName()+"获得到锁");
t1.start();
// t1.interrupt();
// 主线程2s之后才释放锁
Thread.sleep(2);
System.out.println("main线程释放了锁");
lock.unlock();
}
}
输出结果:
main获得到锁
尝试获得锁
main线程释放了锁
t1获得到锁
Process finished with exit code 0
//默认是不公平锁,需要在创建时指定为公平锁
ReentrantLock lock = new ReentrantLock(true);
公平锁 (new ReentrantLock(true))
非公平锁 (synchronized, new ReentrantLock())
等待唤醒
public class ConditionVariable {
private static boolean hasCigarette = false;
private static boolean hasTakeout = false;
private static final ReentrantLock lock = new ReentrantLock();
// 等待烟的休息室
static Condition waitCigaretteSet = lock.newCondition();
// 等外卖的休息室
static Condition waitTakeoutSet = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":有烟没?[{"+hasCigarette+"}]");
while (!hasCigarette) {
System.out.println(Thread.currentThread().getName()+":没烟,先歇会!");
try {
// 此时小南进入到 等烟的休息室
waitCigaretteSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+":烟来咯, 可以开始干活了");
} finally {
lock.unlock();
}
}, "小南").start();
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":外卖送到没?[{"+hasTakeout+"}]");
while (!hasTakeout) {
System.out.println(Thread.currentThread().getName()+":没外卖,先歇会!");
try {
// 此时小女进入到 等外卖的休息室
waitTakeoutSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+":外卖来咯, 可以开始干活了");
} finally {
lock.unlock();
}
}, "小女").start();
Thread.sleep(1000);
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":送外卖的来咯~");
hasTakeout = true;
// 唤醒等外卖的小女线程
waitTakeoutSet.signal();
} finally {
lock.unlock();
}
}, "送外卖的").start();
Thread.sleep(1000);
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":送烟的来咯~");
hasCigarette = true;
// 唤醒等烟的小南线程
waitCigaretteSet.signal();
} finally {
lock.unlock();
}
}, "送烟的").start();
}
}
输出结果:
小南:有烟没?[{false}]
小南:没烟,先歇会!
小女:外卖送到没?[{false}]
小女:没外卖,先歇会!
送外卖的:送外卖的来咯~
小女:外卖来咯, 可以开始干活了
送烟的:送烟的来咯~
小南:烟来咯, 可以开始干活了
Process finished with exit code 0
public class SyncPrintWaitTest {
public static final Object lock = new Object();
// t2线程释放执行过
public static boolean t2IsRunned = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (!t2IsRunned) {
try {
// 进入等待(waitset), 会释放锁
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1");
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("2");
t2IsRunned = true;
lock.notify();
}
}, "t2");
t1.start();
t2.start();
}
}
public class SyncPrintWaitTest {
public static final Lock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
// t2线程释放执行过
public static boolean t2IsRunned = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
while (!t2IsRunned) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1");
}finally {
lock.unlock();
}
}, "t1");
Thread t2 = new Thread(() -> {
lock.lock();
try {
System.out.println("2");
t2IsRunned = true;
condition.signal();
} finally {
lock.unlock();
}
}, "t2");
t1.start();
t2.start();
}
}
public class SyncPrintWaitTest {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
LockSupport.park();
System.out.println("1");
}, "t1");
t1.start();
new Thread(() -> {
System.out.println("2");
LockSupport.unpark(t1);
}, "t2").start();
}
}
public class TestWaitNotify {
public static void main(String[] args) {
WaitNotify waitNotify = new WaitNotify(1, 5);
new Thread(() -> {
waitNotify.print("a", 1, 2);
}, "a线程").start();
new Thread(() -> {
waitNotify.print("b", 2, 3);
}, "b线程").start();
new Thread(() -> {
waitNotify.print("c", 3, 1);
}, "c线程").start();
}
}
@Data
@AllArgsConstructor
class WaitNotify {
private int flag;
// 循环次数
private int loopNumber;
/*
输出内容 等待标记 下一个标记
a 1 2
b 2 3
c 3 1
*/
public void print(String str, int waitFlag, int nextFlag) {
for (int i = 0; i < loopNumber; i++) {
synchronized (this) {
while (waitFlag != this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str);
this.flag = nextFlag;
this.notifyAll();
}
}
}
}
public class TestAwaitSignal {
public static void main(String[] args) throws InterruptedException {
AwaitSignal awaitSignal = new AwaitSignal(5);
Condition a_condition = awaitSignal.newCondition();
Condition b_condition = awaitSignal.newCondition();
Condition c_condition = awaitSignal.newCondition();
new Thread(() -> {
awaitSignal.print("a", a_condition, b_condition);
}, "a").start();
new Thread(() -> {
awaitSignal.print("b", b_condition, c_condition);
}, "b").start();
new Thread(() -> {
awaitSignal.print("c", c_condition, a_condition);
}, "c").start();
awaitSignal.lock();
try {
a_condition.signal(); //首先唤醒a线程
} finally {
awaitSignal.unlock();
}
}
}
class AwaitSignal extends ReentrantLock {
private final int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
public void print(String str, Condition condition, Condition next) {
for (int i = 0; i < loopNumber; i++) {
lock();
try {
try {
condition.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
unlock();
}
}
}
}
public class TestParkUnpark {
static Thread a;
static Thread b;
static Thread c;
public static void main(String[] args) {
ParkUnpark parkUnpark = new ParkUnpark(5);
a = new Thread(() -> {
parkUnpark.print("a", b);
}, "a");
b = new Thread(() -> {
parkUnpark.print("b", c);
}, "b");
c = new Thread(() -> {
parkUnpark.print("c", a);
}, "c");
a.start();
b.start();
c.start();
LockSupport.unpark(a);
}
}
class ParkUnpark {
private final int loopNumber;
public ParkUnpark(int loopNumber) {
this.loopNumber = loopNumber;
}
public void print(String str, Thread nextThread) {
for (int i = 0; i < loopNumber; i++) {
LockSupport.park();
System.out.print(str);
LockSupport.unpark(nextThread);
}
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有