返回

Lock和Condition的Java并发编程指南(1)

Android

什么是Lock和Condition?

Lock

Lock是Java并发编程中的一种同步机制,用于控制对共享资源的访问。与synchronized不同,Lock提供了更细粒度的同步控制,允许线程以更灵活的方式访问共享资源。Lock接口定义了多种方法,包括lock()、unlock()、tryLock()、tryLock(long, TimeUnit)等,这些方法允许线程获取锁、释放锁、尝试获取锁以及在指定时间内尝试获取锁。

Condition

Condition是Java并发编程中的一种同步机制,用于允许线程等待某个条件满足后再继续执行。Condition接口定义了多种方法,包括await()、signal()和signalAll(),这些方法允许线程等待条件、唤醒单个线程或唤醒所有等待线程。

Lock和Condition的使用方法

获取锁

要获取锁,可以使用Lock接口的lock()方法。lock()方法会一直阻塞线程,直到线程成功获取锁。如果线程在等待锁时被中断,则会抛出InterruptedException异常。

释放锁

要释放锁,可以使用Lock接口的unlock()方法。unlock()方法会释放线程持有的锁,允许其他线程获取锁。

尝试获取锁

要尝试获取锁,可以使用Lock接口的tryLock()方法。tryLock()方法会尝试获取锁,但如果锁已被其他线程持有,则不会阻塞线程,而是立即返回false。

带超时尝试获取锁

要带超时尝试获取锁,可以使用Lock接口的tryLock(long, TimeUnit)方法。tryLock(long, TimeUnit)方法会尝试在指定的时间内获取锁,如果在指定的时间内没有获取到锁,则返回false。

等待条件

要等待条件,可以使用Condition接口的await()方法。await()方法会使线程进入等待状态,直到某个条件满足。当条件满足时,线程将被唤醒并继续执行。

唤醒单个线程

要唤醒单个线程,可以使用Condition接口的signal()方法。signal()方法会唤醒一个正在等待该条件的线程。

唤醒所有线程

要唤醒所有线程,可以使用Condition接口的signalAll()方法。signalAll()方法会唤醒所有正在等待该条件的线程。

Lock和Condition的应用场景

Lock和Condition可以用于各种并发编程场景,包括:

  • 多线程访问共享资源 :Lock和Condition可以用于控制对共享资源的访问,防止多个线程同时访问共享资源导致数据不一致。
  • 线程间通信 :Lock和Condition可以用于实现线程间通信,允许一个线程等待另一个线程完成某个任务后再继续执行。
  • 死锁避免 :Lock和Condition可以用于避免死锁,通过合理的使用Lock和Condition,可以确保线程不会进入死锁状态。

Lock和Condition的优缺点

Lock和Condition具有以下优点:

  • 灵活性 :Lock和Condition提供了更细粒度的同步控制,允许线程以更灵活的方式访问共享资源。
  • 性能 :Lock和Condition的性能优于synchronized,因为Lock和Condition使用了更轻量级的同步机制。

Lock和Condition也具有一些缺点:

  • 复杂性 :Lock和Condition的使用比synchronized复杂,需要更多的编程经验。
  • 死锁风险 :Lock和Condition的使用可能导致死锁,需要仔细设计代码以避免死锁。

Lock和Condition的示例

以下是一个使用Lock和Condition实现多线程访问共享资源的示例:

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

class SharedResource {
    private int value;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void increment() {
        lock.lock();
        try {
            while (value > 0) {
                condition.await();
            }
            value++;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void decrement() {
        lock.lock();
        try {
            while (value <= 0) {
                condition.await();
            }
            value--;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public int getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        SharedResource sharedResource = new SharedResource();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sharedResource.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sharedResource.decrement();
            }
        });

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

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final value: " + sharedResource.getValue());
    }
}

这个示例中,两个线程同时访问共享资源,使用Lock和Condition来控制对共享资源的访问,防止两个线程同时访问共享资源导致数据不一致。