多把锁
当保护的资源没有关联时可以采用多个对象锁实现加锁操作
采用多把锁
- 可以增强并发度
- 如果一个线程需要同时获得多把锁,容易产生死锁
不采用多把锁的情况下
class BigRoom {
public void sleep() {
synchronized (this) {
log.debug("sleeping 2 小时");
Sleeper.sleep(2);
}
}
public void study() {
synchronized (this) {
log.debug("study 1 小时");
Sleeper.sleep(1);
}
}
}
时间上其实是串行运行的

采用多把锁的情况
class BigRoom {
private final Object studyRoom = new Object();
private final Object bedRoom = new Object();
public void sleep() {
synchronized (bedRoom) {
log.debug("sleeping 2 小时");
Sleeper.sleep(2);
}
}
public void study() {
synchronized (studyRoom) {
log.debug("study 1 小时");
Sleeper.sleep(1);
}
}
}
线程可以并发执行

活跃性
死锁
两个线程互相持有对象所需的锁,导致无法运行
线程t1获取不到B锁,线程t2获取不到A锁
@Slf4j
public class ThreadLock {
public static void main(String[] args) {
Object A = new Object();
Object B = new Object();
Thread t1 = new Thread(() -> {
synchronized (A) {
log.debug("lock A");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
log.debug("lock B");
log.debug("操作...");
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (B) {
log.debug("lock B");
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (A) {
log.debug("lock A");
log.debug("操作...");
}
}
}, "t2");
t1.start();
t2.start();
}
}

怎么查找死锁(定位死锁)
- 通过jps查看当前进程id,再通过jstack pid查看线程信息


- 还可使用jconsole查看死锁

- 注意加锁的顺序
- 如果由于某个线程进入了死循环,导致其它线程一直等待,对于这种情况 linux 下可以通过 top 先定位到CPU 占用高的 Java 进程,再利用 top -Hp 进程id 来定位是哪个线程,最后再用 jstack 排查
活锁
两个线程互相改变对方的结束条件导致无法释放锁,可以通过改变两个线程的执行时间去解决
public class TestLiveLock {
static volatile int count = 10;
static final Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
// 期望减到 0 退出循环
while (count > 0) {
sleep(0.2);
count--;
log.debug("count: {}", count);
}
}, "t1").start();
new Thread(() -> {
// 期望超过 20 退出循环
while (count < 20) {
sleep(0.2);
count++;
log.debug("count: {}", count);
}
}, "t2").start();
}
}
饥饿
一个线程因为优先级太低始终得不到CPU调度执行,也不能够结束
像顺序加锁就容易产生饥饿现象

4058

被折叠的 条评论
为什么被折叠?



