一、什么是线程安全问题?
当多个线程同时操作同一个数据时,可能出现数据混乱的情况。就像多个收银员同时操作同一台收银机,可能出现金额错乱。
二、如何保证线程安全?
方法1:同步代码块
private Object lock = new Object(); // 随便创建一个对象当锁
public void sellTicket() {
synchronized(lock) { // 给代码上锁
if(tickets > 0) {
System.out.println("卖出第" + tickets-- + "张票");
}
}
}
注意:锁对象必须唯一(建议用final修饰)
就像给厕所门上锁,同一时间只允许一个人使用
方法2:同步方法
public synchronized void sellTicket() {
// 自动使用当前对象(this)当锁
if(tickets > 0) {
System.out.println("卖出第" + tickets-- + "张票");
}
}
注意:普通方法用this当锁
静态方法用类对象当锁(如MyClass.class)
Thread中同步方法只能用静态方法
方法3:Lock锁(更灵活)
Lock lock = new ReentrantLock(); // 创建锁对象
public void sellTicket() {
lock.lock(); // 手动上锁
try {
if(tickets > 0) {
System.out.println("卖出第" + tickets-- + "张票");
}
} finally {
lock.unlock(); // 必须解锁!
}
}
注意:优点:可中断、可设置超时时间
必须写在finally中保证解锁
三、两种锁对比
synchronized jvm级别的锁,jvm自动上锁和解锁
Lock锁java代码写的锁,需要手动的加锁和释放锁

四、对象锁与类锁
使用 synchronized 关键字来实现线程同步
import java.util.concurrent.TimeUnit;
public class TestThread8 {
public static void main(String[] args) {
// 创建 TestThread8 类的一个实例对象
TestThread8 tt1 = new TestThread8();
// TestThread8 tt2 = new TestThread8();
new Thread(() -> {
tt1.t1();
}).start();
new Thread(() -> {
tt1.t2();
}).start();
}
// 使用 synchronized 块对 TestThread8 类的 Class 对象加锁
public void t1() {
// 这意味着同一时间只有一个线程可以进入该块执行代码
synchronized (TestThread8.class) {
System.out.println("进入 t1 方法");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("结束 t1 方法");
}
}
// 使用 synchronized 关键字修饰
// 静态方法的同步锁是该类的 Class 对象,即 TestThread8.class
public static synchronized void t2() {
System.out.println("进入 t2 方法");
try {
// 线程休眠 3 秒,模拟耗时操作
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("结束 t2 方法");
}
}
五、常见问题解决指南
出现死锁怎么办?
死锁场景:
- 线程A拿着锁1等锁2
- 线程B拿着锁2等锁1
解决方法:
- 按固定顺序获取锁
- 使用
tryLock()设置等待时间if(lock.tryLock(500, TimeUnit.MILLISECONDS)) { // 最多等500ms // 拿到锁后的操作 }
六、最佳实践总结
-
优先使用:
java.util.concurrent包中的线程安全类ConcurrentHashMapCopyOnWriteArrayList
-
锁使用原则:
- 锁的范围尽量小
- 锁对象用
final修饰 - 避免在锁内调用其他方法
-
简单场景用synchronized,复杂需求用Lock锁
10万+

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



