Java锁表和解锁

在Java中,锁(Lock)是一种用于并发控制的机制,用于保护共享资源,确保多线程环境下的数据安全性。锁可以用来同步对临界区的访问,使得同一时刻只有一个线程可以执行临界区代码,其他线程需要等待锁的释放才能继续执行。

1. 为什么需要锁?

在并发编程中,多个线程可能同时访问和修改共享资源,如果不采取任何措施,就会引发竞态条件(Race Condition),导致结果不可预测或不正确。为了避免竞态条件,我们需要使用锁来保护共享资源,以确保线程间的协调和同步。

2. Java中的锁类型

Java提供了多种类型的锁,常用的有synchronized关键字和ReentrantLock类。下面我们分别介绍这两种锁的使用方式。

2.1 synchronized关键字

synchronized关键字是Java语言内置的一种锁机制,可以用来修饰方法或代码块。当线程进入synchronized修饰的方法或代码块时,会自动获取锁,其他线程需要等待锁的释放才能执行。

示例代码如下:

public class SynchronizedExample {
    private int count = 0;

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

    public synchronized int getCount() {
        return count;
    }
}

在上述示例中,increment()和getCount()方法都被synchronized修饰,这意味着同一时刻只有一个线程可以执行这两个方法。这样就保证了count的操作是原子的,避免了数据不一致的问题。

2.2 ReentrantLock类

ReentrantLock是Java.util.concurrent包中的一个锁实现类,它提供了更灵活的锁控制,相比于synchronized关键字,它更加可扩展和可定制。

示例代码如下:

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private int count = 0;
    private ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

在上述示例中,increment()和getCount()方法使用ReentrantLock进行加锁和解锁。使用try-finally语句块确保无论是否发生异常,都能正确释放锁。

3. 锁的特性

锁除了提供基本的加锁和解锁功能外,还提供了其他一些重要的特性,如可重入性、公平性和条件变量。

3.1 可重入性

可重入性是指同一个线程可以多次获取同一个锁,而不会发生死锁。synchronized关键字和ReentrantLock类都是可重入锁,这意味着一个线程可以重复获取已经持有的锁,而不会造成死锁。

3.2 公平性

公平性是指多个线程按照其发出请求的顺序获得锁的机制。synchronized关键字默认是非公平锁,即无法保证多个线程获取锁的顺序。而ReentrantLock类可以根据构造函数传入的参数来指定锁的公平性。

3.3 条件变量

条件变量是指在锁的基础上,对线程进行更精细的控制和协调的机制。在Java中,可以使用Condition接口和ReentrantLock类的newCondition()方法来实现条件变量。

示例代码如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionExample {
    private int count = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
        lock.lock();
        try {
            count++;