Java锁Synchronized的使用

在多线程编程中,为了保证共享资源的安全访问,我们需要使用锁来控制线程的访问顺序和互斥访问。Java中的Synchronized关键字是一种加锁机制,可以用于方法或代码块,用于实现线程的同步。

什么是Synchronized关键字?

Synchronized是Java中用于实现线程同步的关键字,它可以用于修饰方法和代码块。当一个方法或代码块被Synchronized修饰时,它就变成了一个同步方法或同步代码块。在同步方法或代码块中,一次只能有一个线程访问该方法或代码块,其他线程必须等待。

Synchronized的基本用法

同步方法

首先,我们来看一下Synchronized关键字在方法上的使用。当我们将一个方法声明为Synchronized时,该方法成为一个同步方法。

public class SynchronizedExample {

    private int count = 0;

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

上面的代码中,我们声明了一个名为increment的同步方法,该方法的作用是将count的值增加1。由于该方法被Synchronized修饰,因此在同一时间只能有一个线程访问该方法。

同步代码块

除了在方法上使用Synchronized关键字,我们还可以在代码块中使用它来实现同步。下面是一个示例:

public class SynchronizedExample {

    private int count = 0;
    private Object lock = new Object();

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

在上面的代码中,我们使用了一个对象lock来实现同步。在increment方法中,我们使用了一个Synchronized代码块,该代码块的锁对象是lock。这样,同一时间只能有一个线程访问该代码块。

Synchronized的使用场景

Synchronized关键字的使用场景通常是在多线程访问共享资源的情况下。下面是几个常见的使用场景:

1. 多线程访问共享变量

当多个线程同时访问一个共享变量时,我们需要使用Synchronized来保证对该变量的互斥访问,以避免数据不一致的问题。

public class SynchronizedExample {

    private int count = 0;

    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

在上面的代码中,increment方法和getCount方法都被声明为同步方法。这样,当多个线程同时调用这两个方法时,对count变量的访问就是互斥的。

2. 保护共享资源

在多线程环境中,有时候我们需要保护一段关键代码,使得只有一个线程能够执行它。这时候,我们可以使用Synchronized代码块来实现。

public class SynchronizedExample {

    private int count = 0;
    private Object lock = new Object();

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
    
    public void decrement() {
        synchronized (lock) {
            count--;
        }
    }
}

在上面的代码中,increment方法和decrement方法都使用了Synchronized代码块,并且使用了同一个锁对象lock。这样,同一时间只能有一个线程执行这两个方法。

3. 线程安全的集合类

在Java中,有一些集合类不是线程安全的,比如ArrayList、HashMap等。如果我们需要在多线程环境下使用这些集合类,就需要使用Synchronized来保证它们的线程安全性。

List<String> list = Collections.synchronizedList(new ArrayList<>());
Map<String, String> map = Collections.synchronizedMap(new HashMap<>());

在上面的代码中,我们通过Collections类的静态方法创建了一个线程安全的List和Map。这样,我们就可以在多线程环境中安全地使用它们。