Java高并发编程实战:深入浅出那些年学过的锁

作者:问题终结者2024.01.17 12:26浏览量:5

简介:本文将深入探讨Java中常见的锁机制,包括synchronized、ReentrantLock、Semaphore、CountDownLatch等,并给出实践中的建议。

Java作为一门广泛应用于高并发编程的语言,提供了多种锁机制来确保线程安全。了解和掌握这些锁机制是Java程序员必备的技能之一。本文将带您深入浅出地了解那些年学过的锁,包括synchronized、ReentrantLock、Semaphore、CountDownLatch等,并通过实例演示它们的用法。

  1. synchronized
    synchronized是Java中最基本的锁机制,它提供了互斥访问共享资源的能力。synchronized可以修饰方法或代码块,当一个线程进入synchronized代码块或方法时,会获取锁,其他线程则需要等待锁释放后才能进入。synchronized的优点是简单易用,但缺点是只支持单个线程访问同步代码块,且无法中断获取不到锁的线程。
  2. ReentrantLock
    ReentrantLock是Java 5之后引入的锁机制,它提供了与synchronized类似的功能,但更加灵活。ReentrantLock可以重复获取锁,即当一个线程已经持有锁时,可以再次获取到同一个锁,而不会产生死锁。此外,ReentrantLock还提供了tryLock()方法,该方法尝试获取锁但立即返回,不会阻塞线程。ReentrantLock还支持中断获取锁的线程。
    示例:
    1. ReentrantLock lock = new ReentrantLock();
    2. lock.lock();
    3. try {
    4. // 访问共享资源
    5. } finally {
    6. lock.unlock();
    7. }
  3. Semaphore
    Semaphore是一种计数信号量锁,用于控制对共享资源的访问权限。Semaphore的优点是可以同时控制多个线程对共享资源的访问。通过Semaphore对象来控制共享资源的访问,需要调用acquire()方法获取许可,使用完共享资源后需要调用release()方法释放许可。当没有许可可用时,acquire()方法会使线程阻塞,直到获取到许可为止。
    示例:
    1. Semaphore semaphore = new Semaphore(1); // 初始许可数量为1
    2. semaphore.acquire(); // 获取许可
    3. try {
    4. // 访问共享资源
    5. } finally {
    6. semaphore.release(); // 释放许可
    7. }
  4. CountDownLatch
    CountDownLatch是一种倒计时计数器锁,用于同步一组线程的执行顺序。CountDownLatch的初始化时指定一个计数值,线程执行完毕后调用countDown()方法减少计数器值。当计数器值为0时,等待的线程会被唤醒并继续执行。CountDownLatch适用于多个线程需要等待某个条件满足后才能继续执行的场景。
    示例:
    1. CountDownLatch latch = new CountDownLatch(3); // 初始计数值为3
    2. for (int i = 0; i < 5; i++) {
    3. new Thread(() -> {
    4. // 执行任务...
    5. latch.countDown(); // 任务执行完毕后减少计数器值
    6. }).start();
    7. }
    8. latch.await(); // 等待计数器值为0,即所有任务执行完毕后继续执行后续代码...
    总结:在高并发编程中,选择合适的锁机制非常重要。synchronized适用于简单的互斥访问共享资源的情况;ReentrantLock更加灵活,适用于需要重复获取锁或支持中断获取锁的情况;Semaphore适用于控制多个线程对共享资源的访问;CountDownLatch适用于同步一组线程的执行顺序的场景。在实际应用中,需要根据具体需求选择合适的锁机制,并注意避免死锁和性能问题。