在Java中,`synchronized`块是一种常用的多线程同步机制,它允许你在一个代码块上加上锁,以防止多个线程同时执行该代码块中的代码。这对于共享资源的访问控制非常重要,可以避免数据不一致和竞态条件。
以下是一个使用`synchronized`块同步方法的简单示例:
public class Counter {
// 共享资源
private int count = 0;
// 使用synchronized块来同步方法
public void increment() {
// 锁定当前对象(this)
synchronized (this) {
// 只有当获得锁后,这个块内的代码才会被执行
// 这里是临界区,确保同时只有一个线程能执行
count++;
}
// 锁在块结束时自动释放
}
// 另一个方法,演示如何安全地获取count的值
public synchronized int getCount() {
// 这个方法也是同步的,但整个方法体都是临界区
// 你可以根据需求选择是同步整个方法还是同步代码块
return count;
}
public static void main(String[] args) throws InterruptedException {
final Counter counter = new Counter();
// 创建并启动线程
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
// 等待两个线程完成
thread1.join();
thread2.join();
// 输出最终结果
System.out.println("Final count: " + counter.getCount());
// 理想情况下,应该是2000,因为每个线程都增加了1000
}
}
在这个例子中,`increment`方法使用`synchronized`块来确保`count++`操作的原子性。尽管`++`操作本身不是原子的,但在`synchronized`块中,它会被当作一个不可分割的操作执行。
同时,`getCount`方法也被声明为`synchronized`,这意味着每次只有一个线程能进入这个方法。然而,在这个例子中,将整个方法设为同步可能是不必要的,因为只有返回操作可能受到并发的影响,但这通常不是问题,因为`int`的读取是原子的(尽管在复杂场景下可能需要更精细的控制)。
注意,`synchronized`块通常比同步整个方法更灵活,因为它允许你更精确地控制哪些代码需要同步,从而减少锁的范围,提高程序的性能。