在 Java 中,每一个对象都可以作为一把锁,synchronized
通过获取对象头中的锁标志位来实现同步。当一个线程获取到对象的锁后,其他线程就无法再获取该锁,只能等待获取到锁的线程释放锁之后才能继续执行被 synchronized 修饰的代码块或方法。synchronized
本质上就是 Java 语言层面实现的一种互斥锁
背景
为了增加并发度,降低锁的粒度,增加多把锁;
一间大屋子有两个功能:睡觉、学习,互不相干。 现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低 解决方法是准备多个房间(多个对象锁)
package cn.itcast.n4;
import static cn.itcast.n2.util.Sleeper.sleep;
import cn.itcast.n2.util.Sleeper;
import lombok.extern.slf4j.Slf4j;
public class TestMultiLock {
public static void main(String[] args) {
BigRoom bigRoom = new BigRoom();
new Thread(() -> {
bigRoom.study();
},"小南").start();
new Thread(() -> {
bigRoom.sleep();
},"小女").start();
}
}
@Slf4j(topic = "c.BigRoom")
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);
}
}
}
死锁问题
如果出现一个线程同时获取多把锁的情况,而且不是按照相同的顺序加锁的,可能会出现死锁问题
package cn.itcast.n4.deadlock;
import lombok.extern.slf4j.Slf4j;
import static cn.itcast.n2.util.Sleeper.sleep;
@Slf4j(topic = "c.TestDeadLock")
public class TestDeadLock {
public static void main(String[] args) {
test1();
}
private static void test1() {
Object A = new Object();
Object B = new Object();
Thread t1 = new Thread(() -> {
synchronized (A) {
log.debug("lock A");
sleep(1);
synchronized (B) {
log.debug("lock B");
log.debug("操作...");
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (B) {
log.debug("lock B");
sleep(0.5);
synchronized (A) {
log.debug("lock A");
log.debug("操作...");
}
}
}, "t2");
t1.start();
t2.start();
}
}
定位
解决
按照相同的顺序加锁