Java中关键字synchronized的使用方法详解

下面我将详细讲解 Java 中关键字 synchronized 的使用方法。

下面我将详细讲解 Java 中关键字 synchronized 的使用方法。

什么是 synchronized

synchronized 是 Java 中的关键字,用来保证线程安全。

在 Java 中,当多个线程访问同一资源时,如果没有对这个资源加锁,可能会发生数据不一致的情况。而使用 synchronized 关键字可以保证在同一时刻只有一个线程可以访问一个方法或一个代码块,从而避免多线程并发访问的问题。

synchronized 的使用方法

synchronized 有两种使用方式:对方法加锁和对代码块加锁。

对方法加锁

对方法加锁的方式是在方法的声明处添加 synchronized 关键字。这种方式会将整个方法锁住,使得同一时刻只能有一个线程进入方法。

下面是一个对方法加锁的示例:

public synchronized void method() {
    // synchronized代码块
}

对代码块加锁

对代码块加锁的方式是使用 synchronized 关键字包围需要保证线程安全的代码块。这种方式可以灵活地控制同步的范围,只对关键代码块进行同步,提高多线程并发执行的效率。

下面是一个对代码块加锁的示例:

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

synchronized 的局限性

synchronized 关键字虽然可以保证线程安全,但也有其局限性。synchronized 同步的范围只能是当前线程的同一个进程,无法同步不同进程之间的数据同步。

此外,在锁的范围过大时,可能会出现死锁的情况。因此,在使用 synchronized 时,需要合理设计锁的范围,避免出现死锁和锁竞争等问题。

示例说明

下面,我们给出两个示例,分别是对方法加锁和对代码块加锁的示例。

示例一:对方法加锁

public class SynchronizedTest {

    private int count = 0;

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

    public synchronized void decrement() {
        count--;
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        final SynchronizedTest test = new SynchronizedTest();
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        test.increment();
                        test.decrement();
                    }
                }
            }.start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(test.getCount());
    }
}

在这个示例中,我们创建了一个 SynchronizedTest 类,该类有两个方法 increment 和 decrement,分别用于对 count 进行加一和减一操作。为了保证线程安全,我们在这两个方法的声明处使用了 synchronized 关键字。

在 main 方法中,我们创建了 10 个线程,并且让它们同时执行 increment 和 decrement 方法。由于我们在这两个方法中使用了 synchronized 关键字,因此,在同一时刻,只有一个线程可以访问这两个方法,从而保证了线程安全。

最后,我们输出 count 的值,可以发现最后的结果是 0,说明我们的加一和减一操作是成对出现的,程序运行正确。

示例二:对代码块加锁

public class SynchronizedTest {

    private int count = 0;

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

    public int getCount() {
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        final SynchronizedTest test = new SynchronizedTest();
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        test.add();
                    }
                }
            }.start();
        }
        Thread.sleep(1000);
        System.out.println(test.getCount());
    }
}

在这个示例中,我们同样创建了一个 SynchronizedTest 类,该类有一个方法 add,用于对 count 进行加一操作。

不同的是,在 add 方法中,我们对代码块进行了同步。这个代码块使用 synchronized(this) 关键字对 this 对象进行加锁,从而保证了线程安全。

在 main 方法中,我们同样创建了 10 个线程,并且让它们同时执行 add 方法,由于我们使用了代码块加锁的方式,在同一时刻,只有一个线程可以访问 add 方法,从而保证了线程安全。

同样地,最后我们输出 count 的值,可以发现最后的结果是 10000,也说明了我们的加一操作是正确的。

本文标题为:Java中关键字synchronized的使用方法详解

基础教程推荐