Java同步方式

在多线程编程中,同步是一种重要的技术,用于解决多线程访问共享资源时可能出现的并发问题。Java提供了多种同步方式,包括使用synchronized关键字、使用ReentrantLock类、使用volatile关键字等。本文将逐一介绍这些同步方式的特点和使用方法,并给出相应的代码示例。

1. 使用synchronized关键字

synchronized关键字是Java语言提供的最基本的同步方式。它可以应用于方法和代码块,用于保证同一时间只有一个线程可以访问被同步的资源。

在方法上使用synchronized关键字时,整个方法被称为同步方法。以下是一个使用synchronized关键字实现的示例:

public class SynchronizedExample {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized void decrement() {
        count--;
    }
}

在上面的代码中,increment()decrement()方法都被标记为synchronized,这意味着同一时间只能有一个线程执行这些方法,从而保证了count变量的线程安全性。

除了同步方法外,synchronized关键字还可以应用于代码块。以下是一个使用synchronized关键字实现的代码块示例:

public class SynchronizedExample {
    private Object lock = new Object();
    private int count = 0;
    
    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
    
    public void decrement() {
        synchronized (lock) {
            count--;
        }
    }
}

上述代码中,increment()decrement()方法内部的代码块都被synchronized关键字包围,这意味着同一时间只能有一个线程进入代码块内部执行。

2. 使用ReentrantLock

ReentrantLock类是Java提供的另一种同步方式,相对于synchronized关键字,ReentrantLock类提供了更高级的功能,如可重入性、公平性等。

以下是一个使用ReentrantLock类实现的示例:

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private ReentrantLock lock = new ReentrantLock();
    private int count = 0;
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    
    public void decrement() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }
}

在上面的代码中,increment()decrement()方法内部分别调用了lock()unlock()方法,确保了在访问共享资源时只有持有锁的线程可以执行相应的代码。与synchronized关键字不同,ReentrantLock类可以使用try-finally语句来确保在发生异常时能够正确释放锁。

3. 使用volatile关键字

volatile关键字是Java提供的一种轻量级同步机制,主要用于保证变量的可见性和禁止指令重排序。

以下是一个使用volatile关键字实现的示例:

public class VolatileExample {
    private volatile int count = 0;
    
    public void increment() {
        count++;
    }
    
    public void decrement() {
        count--;
    }
}

在上述代码中,count变量被声明为volatile,这意味着每次访问该变量时都会从主内存中读取最新的值,并且每次修改该变量时都会立即写回主内存。

比较不同同步方式的特点

下表列出了SynchronizedReentrantLockVolatile这三种同步方式的特点:

特点 Synchronized ReentrantLock Volatile
机制 互斥锁 互斥锁 内存可见性和禁止指令重排序
可重入性