java多线程编程之使用Synchronized块同步方法


在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`块通常比同步整个方法更灵活,因为它允许你更精确地控制哪些代码需要同步,从而减少锁的范围,提高程序的性能。