在多线程编程中,当多个线程同时访问共享资源时,可能会导致数据不一致或者意外行为。Java提供了多种线程同步机制,其中同步方法是最基础、最常用的一种。
同步方法的核心机制
通过在方法声明中加入synchronized关键字,我们可以创建一个同步方法:
public synchronized void increment() {
count++;
}
当一个线程进入同步方法时,它会自动获取该方法所在对象的锁(对于实例方法)或类的Class对象的锁(对于静态方法),其他线程将被阻塞,直到该线程执行完毕并释放锁。
深入理解同步锁
每个Java对象都有一个内置锁(monitor lock),同步方法就是利用这一特性实现的。这种锁是可重入的,意味着一个线程可以多次获取同一个锁,避免了自身死锁。
同步方法不仅保证了操作的原子性,还确保了内存可见性:当释放锁时,所有修改都会刷新到主内存;当获取锁时,本地缓存失效,直接从主内存读取数据。
代码示例:对比同步前后
class Counter {
private int count = 0;
// 非同步方法 - 线程不安全
public void unsafeIncrement() {
count++;
}
// 同步方法 - 线程安全
public synchronized void safeIncrement() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class SynchronizedMethodDemo {
public static void main(String[] args) throws InterruptedException {
final Counter counter = new Counter();
// 创建多个线程并发访问
Thread[] threads = new Thread[1000];
for (int i = 0; i < 1000; i++) {
threads[i] = new Thread(() -> {
counter.safeIncrement(); // 尝试改为unsafeIncrement观察结果
});
threads[i].start();
}
// 等待所有线程完成
for (Thread thread : threads) {
thread.join();
}
System.out.println("最终计数: " + counter.getCount());
// 使用safeIncrement总是输出1000,unsafeIncrement则可能小于1000
}
}
同步方法的优缺点
优点:
- 使用简单,语法简洁
- 自动管理锁的获取和释放,避免人为失误
- 可重入性避免了自我死锁
缺点:
- 粗粒度锁可能导致性能瓶颈
- 无法中断正在等待获取锁的线程
- 不支持尝试获取锁(tryLock)功能
总结
同步方法是Java线程同步的基础工具,适用于简单的同步场景。理解其底层机制和局限性对于编写高效、安全的多线程程序至关重要。在更复杂的并发场景中,可能需要结合使用Java并发包中的高级同步机制,如ReentrantLock、Semaphore等。

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



