跳至主要內容

Java多线程教程:多线程同步机制

程序猿DD原创JavaJava大约 3 分钟

Java多线程教程:多线程同步机制

Java中的同步机制是一种强大的工具,用于控制多个线程对共享资源的访问。它确保同一时间只有一个线程可以访问资源,防止数据不一致和竞态条件。这在多线程环境中尤为重要,因为线程经常共享变量、数组或对象等资源。

目录

  1. 同步概述
  2. 同步方法
  3. 同步块
  4. 静态同步
  5. 示例:同步方法
  6. 示例:同步块
  7. 可重入同步
  8. 同步与性能
  9. 结论

1. 同步概述

在Java中,synchronized关键字用于同步对代码临界区的访问。主要有两种同步方式:

  • 同步方法:整个方法标记为synchronized,确保同一时间只有一个线程执行该方法。
  • 同步块:方法内的特定代码块标记为synchronized,提供更细粒度的同步控制。

2. 同步方法

同步方法确保同一对象实例上的该方法同一时间只能被一个线程执行。锁由调用该方法的对象实例持有。

语法:

public synchronized void synchronizedMethod() {
    // 同步代码
}

3. 同步块

同步块是方法内针对特定对象的同步代码块。它允许只锁定代码的关键部分而非整个方法。

语法:

public void method() {
    synchronized (this) {
        // 同步代码
    }
}

4. 静态同步

静态同步确保获取的是类级锁,所有类实例共享同一把锁。

语法:

public static synchronized void staticSynchronizedMethod() {
    // 同步代码
}

或使用同步块:

public static void staticMethod() {
    synchronized (ClassName.class) {
        // 同步代码
    }
}

5. 示例:同步方法

代码示例:

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedMethodExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("最终计数: " + counter.getCount());
    }
}

输出结果:

最终计数: 2000

代码解释:

  • Counter类的increment方法被声明为synchronized
  • 两个线程各执行1000次increment操作。
  • 最终计数为2000,说明同步机制避免了竞态条件。

6. 示例:同步块

代码示例:

class Counter {
    private int count = 0;

    public void increment() {
        synchronized (this) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedBlockExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("最终计数: " + counter.getCount());
    }
}

输出结果:

最终计数: 2000

代码解释:

  • increment方法使用synchronized (this)同步块。
  • 与同步方法示例效果相同,确保线程安全。

7. 可重入同步

Java的同步锁是可重入的。如果线程已持有某个对象的锁,它可以再次进入该对象的任何同步方法或块。

示例代码:

class ReentrantExample {
    public synchronized void method1() {
        System.out.println("进入 method1");
        method2();
    }

    public synchronized void method2() {
        System.out.println("进入 method2");
    }

    public static void main(String[] args) {
        ReentrantExample example = new ReentrantExample();
        example.method1();
    }
}

输出结果:

进入 method1
进入 method2

代码解释:

  • method1调用synchronizedmethod2
  • 线程可重入已持有的锁,体现可重入性。

8. 同步与性能

同步虽然是线程安全的关键,但获取和释放锁的开销可能影响性能。为减少竞争,应尽可能缩小同步代码的范围。

9. 结论

Java同步机制用于确保多线程环境下的线程安全,防止竞态条件。通过同步方法、同步块和静态同步,可以控制多线程对共享资源的访问。但需谨慎使用同步,平衡线程安全与性能。

上次编辑于:
贡献者: 程序猿DD