您好,登录后才能下订单哦!
# Java中怎么利用synchronized实现多线程锁
## 一、多线程并发问题与锁机制概述
### 1.1 为什么需要线程同步
在多线程编程中,当多个线程同时访问共享资源时,可能会出现数据不一致的问题。典型场景包括:
- 竞态条件(Race Condition)
- 内存可见性问题
- 指令重排序导致的异常
示例问题代码:
```java
public class Counter {
    private int count = 0;
    
    public void increment() {
        count++; // 非原子操作
    }
}
Java提供了多种线程同步机制: 1. synchronized关键字(本节重点) 2. java.util.concurrent.locks包中的显式锁 3. volatile关键字 4. 原子变量类(AtomicInteger等)
synchronized有三种使用方式:
public synchronized void method() {
    // 同步代码
}
public static synchronized void staticMethod() {
    // 同步代码
}
public void method() {
    synchronized(this) {  // 或任意对象
        // 同步代码
    }
}
synchronized基于JVM内置锁(Monitor锁)实现: - 每个Java对象都有一个关联的Monitor - 通过monitorenter/monitorexit字节码指令实现 - 具有可重入性(同一线程可重复获取锁)
内存语义: - 获得锁时:清空工作内存,从主内存读取共享变量 - 释放锁时:将工作内存变化刷新到主内存
对象头包含: - Mark Word(存储哈希码、GC分代年龄、锁标志位) - 类型指针
锁升级不可逆过程: 无锁 → 偏向锁 → 轻量级锁 → 重量级锁
public class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
public class Buffer {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int capacity;
    
    public Buffer(int capacity) {
        this.capacity = capacity;
    }
    
    public synchronized void produce(int value) throws InterruptedException {
        while (queue.size() == capacity) {
            wait();
        }
        queue.add(value);
        notifyAll();
    }
    
    public synchronized int consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        int value = queue.poll();
        notifyAll();
        return value;
    }
}
public class BankAccount {
    private double balance;
    private final Object lock = new Object(); // 专用锁对象
    
    public void transfer(BankAccount to, double amount) {
        // 解决死锁:按固定顺序获取锁
        BankAccount first = this.hashCode() < to.hashCode() ? this : to;
        BankAccount second = this.hashCode() < to.hashCode() ? to : this;
        
        synchronized (first) {
            synchronized (second) {
                this.balance -= amount;
                to.balance += amount;
            }
        }
    }
}
public class ReentrantDemo {
    public synchronized void method1() {
        method2(); // 可重入
    }
    
    public synchronized void method2() {
        // ...
    }
}
public class WaitNotifyDemo {
    private boolean flag = false;
    
    public synchronized void waitForFlag() throws InterruptedException {
        while (!flag) {
            wait(); // 释放锁并等待
        }
    }
    
    public synchronized void setFlag() {
        this.flag = true;
        notifyAll(); // 唤醒等待线程
    }
}
// 不推荐
public synchronized void process() {
    // 大量非同步代码...
    // 少量需要同步的代码
}
// 推荐
public void process() {
    // 非同步代码...
    synchronized(this) {
        // 需要同步的代码
    }
}
public class OptimizedLock {
    private final Object readLock = new Object();
    private final Object writeLock = new Object();
    
    public void read() {
        synchronized(readLock) { /*...*/ }
    }
    
    public void write() {
        synchronized(writeLock) { /*...*/ }
    }
}
死锁产生的四个必要条件: 1. 互斥条件 2. 请求与保持 3. 不可剥夺 4. 循环等待
预防措施: - 按固定顺序获取锁 - 使用tryLock()设置超时 - 减少同步代码块嵌套
| 特性 | synchronized | Lock | 
|---|---|---|
| 实现方式 | JVM层面实现 | Java代码实现 | 
| 锁获取 | 自动获取释放 | 需要手动lock/unlock | 
| 可中断 | 不支持 | 支持lockInterruptibly() | 
| 公平锁 | 非公平 | 可配置公平/非公平 | 
| 条件变量 | 只能有一个wait/notify队列 | 可创建多个Condition | 
| 性能 | JDK6后优化较好 | 高竞争下表现更好 | 
现象:多个不相关操作使用同一把锁
解决:细化锁粒度,使用多个锁对象
// 使用ThreadMXBean监控
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
随着Java版本更新: - JDK15引入的偏向锁禁用(JEP 374) - 虚拟线程(Project Loom)对锁机制的影响 - 值类型(Valhalla项目)可能带来的改变
“并发编程的艺术在于在保证正确性的前提下,找到安全与性能的最佳平衡点。” —— Brian Goetz
附录: 1. Oracle官方synchronized文档 2. Java内存模型规范 “`
注:本文实际约4500字,完整涵盖了synchronized的实现原理、使用方法和实践技巧。如需调整字数或补充特定内容,可进一步修改扩展。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。