首页 > 编程语言 >Java中的ReentrantLock详解

Java中的ReentrantLock详解

时间:2024-07-14 15:43:00浏览次数:18  
标签:Java Thread lock void ReentrantLock 详解 new public

Java中的ReentrantLock详解

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

在Java编程中,多线程同步是一个常见的需求。为了保证多个线程对共享资源的安全访问,Java提供了多种锁机制,其中ReentrantLock是一个重要的工具。本文将详细介绍ReentrantLock的使用,包括其基本操作、与synchronized的对比、条件变量的使用等。

1. ReentrantLock的基本使用

ReentrantLock是一个可重入锁,意味着一个线程可以多次获取同一把锁而不会被阻塞。以下是一个简单的示例:

package cn.juwatech.lock;

import java.util.concurrent.locks.ReentrantLock;

public class BasicUsage {
    private final ReentrantLock lock = new ReentrantLock();
    private int counter = 0;

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

    public int getCounter() {
        return counter;
    }

    public static void main(String[] args) throws InterruptedException {
        BasicUsage usage = new BasicUsage();
        Runnable task = usage::increment;

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Final counter: " + usage.getCounter());
    }
}

在这个示例中,lock.lock()用于获取锁,lock.unlock()用于释放锁。在try块中进行实际操作,以确保无论操作是否抛出异常,锁都能被释放。

2. 与synchronized的对比

ReentrantLocksynchronized关键字都可以用于实现线程同步,但它们有一些不同之处:

  • 功能丰富ReentrantLock提供了比synchronized更多的功能,如定时锁、可中断锁等。
  • 性能:在高竞争情况下,ReentrantLock通常比synchronized性能更好。
  • 灵活性ReentrantLock可以更灵活地控制锁的获取和释放。

以下是一个示例,展示了定时锁和可中断锁的使用:

package cn.juwatech.lock;

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

public class AdvancedUsage {
    private final ReentrantLock lock = new ReentrantLock();

    public void timedLock() {
        try {
            if (lock.tryLock(1, TimeUnit.SECONDS)) {
                try {
                    System.out.println("Lock acquired");
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println("Could not acquire lock");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void interruptibleLock() {
        try {
            lock.lockInterruptibly();
            try {
                System.out.println("Lock acquired");
            } finally {
                lock.unlock();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        AdvancedUsage usage = new AdvancedUsage();
        Thread t1 = new Thread(usage::timedLock);
        Thread t2 = new Thread(usage::interruptibleLock);

        t1.start();
        t2.start();
    }
}

3. 使用Condition实现更复杂的同步

ReentrantLock提供了Condition对象来实现更加复杂的线程同步。Condition类似于传统的Object监视器方法(waitnotifynotifyAll),但功能更强大和灵活。

以下是一个使用Condition实现生产者-消费者模式的示例:

package cn.juwatech.lock;

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

public class ProducerConsumer {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_SIZE = 10;

    public void produce(int value) {
        lock.lock();
        try {
            while (queue.size() == MAX_SIZE) {
                notFull.await();
            }
            queue.add(value);
            System.out.println("Produced: " + value);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    public void consume() {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            int value = queue.poll();
            System.out.println("Consumed: " + value);
            notFull.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();
        
        Runnable producerTask = () -> {
            for (int i = 0; i < 20; i++) {
                pc.produce(i);
            }
        };

        Runnable consumerTask = () -> {
            for (int i = 0; i < 20; i++) {
                pc.consume();
            }
        };

        Thread producerThread = new Thread(producerTask);
        Thread consumerThread = new Thread(consumerTask);

        producerThread.start();
        consumerThread.start();
    }
}

在这个示例中,我们使用了两个Condition对象:notFullnotEmpty,分别用于控制队列的满和空状态。生产者在队列满时等待,在生产新数据后通知消费者;消费者在队列空时等待,在消费数据后通知生产者。

4. 公平锁与非公平锁

ReentrantLock可以通过构造函数参数指定为公平锁或非公平锁。公平锁保证锁的获取顺序是按照请求顺序,而非公平锁则允许抢占。

package cn.juwatech.lock;

import java.util.concurrent.locks.ReentrantLock;

public class FairLockUsage {
    private final ReentrantLock fairLock = new ReentrantLock(true);

    public void accessResource() {
        fairLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " acquired the lock");
        } finally {
            fairLock.unlock();
        }
    }

    public static void main(String[] args) {
        FairLockUsage usage = new FairLockUsage();
        
        Runnable task = usage::accessResource;
        
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(task);
            t.start();
        }
    }
}

在这个示例中,我们创建了一个公平锁,通过传递trueReentrantLock的构造函数来实现。

总结

通过上述示例,我们详细介绍了ReentrantLock的各种功能和用法,包括基本使用、与synchronized的对比、条件变量的使用以及公平锁和非公平锁的区别。ReentrantLock提供了比synchronized更灵活和强大的锁机制,是Java并发编程中不可或缺的工具。

著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!

标签:Java,Thread,lock,void,ReentrantLock,详解,new,public
From: https://www.cnblogs.com/szk123456/p/18301630

相关文章

  • 深入理解Java中的反射机制
    深入理解Java中的反射机制大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java开发中,反射机制是一种非常强大的工具,它允许程序在运行时检查和操作类、方法、字段等。反射机制不仅在框架开发中有着广泛的应用,而且在某些动态需求场景中也是必不可少的。本......
  • Java中的垃圾回收机制详解
    Java中的垃圾回收机制详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java中,垃圾回收机制(GarbageCollection,GC)是自动管理内存的一项重要特性。它能够自动释放不再使用的对象所占用的内存,减少内存泄漏和程序崩溃的风险。本文将深入探讨Java中的垃......
  • Java并发编程中的锁机制详解
    Java并发编程中的锁机制详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java并发编程中,锁机制是保证线程安全的重要手段。锁的作用是确保同一时刻只有一个线程能够访问被锁保护的资源,从而避免数据不一致和并发冲突。本文将详细介绍Java并发编程中的......
  • 细粒度掌控:精通Gradle中Java插件的配置艺术
    细粒度掌控:精通Gradle中Java插件的配置艺术引言Gradle是一个灵活且功能丰富的构建工具,它通过插件扩展其功能。Java插件是Gradle中最常用的插件之一,为Java项目提供了丰富的构建生命周期任务和约定。合理配置Java插件,可以极大提升Java项目的构建效率和质量。Java插件简介G......
  • JAVA入门到精通:第一课
    一、JDK下载1、访问oracle官网,选择Java建议选择Java17(长期支持版本)2、选择合适的安装包3、安装过程:傻瓜式“下一步”安装安装路径:建议创建一个新的文件夹,在D盘统一管理4、安装完成后,路径中的文件目录如下所示bin:是最重要的文件夹二、HelloWord程序编写1、记事本......
  • Java基础(For循环/While循环/一维数组/二维数组)
    for循环语句for循环语句中两个分号是绝对不能少的,其他不可以没有,此时for循环就成了死循环。publicclassForDemo{ publicstaticvoidmain(String[]args) { //死循环 for(;;) { System.out.println("for---"); } }}while循环语句格式:初始......
  • Java零基础-集合:集合框架中的工具类
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的......
  • 记录些Java题集(1)
    接口防刷机制接口被刷指的是同一接口被频繁调用,可能是由于以下原因导致:恶意攻击:攻击者利用自动化脚本或工具对接口进行大量请求,以消耗系统资源、拖慢系统响应速度或达到其他恶意目的。误操作或程序错误:某些情况下,程序错误或误操作可能导致接口被重复调用,例如循环调用或者定时......
  • 详解tcp四次挥手
    TCP四次挥手详解TCP四次挥手用于关闭客户端和服务器之间的连接。它确保双方能够有序地终止连接,避免数据丢失。四次挥手的过程第一次挥手:客户端发送FIN报文客户端向服务器发送一个FIN(Finish)报文,请求终止连接。报文包含一个序列号,如FIN=1,seq=x。意义:客户端通知服务......
  • Java 异常艺术:自定义异常的魔力——解锁编程的新维度
    超越常规的错误管理在编程的宇宙中,错误和异常如同星云般存在,既神秘又充满挑战。Java的异常处理机制,尤其是自定义异常,为我们提供了驾驭这一领域的强大工具。本文将引领你深入自定义异常的奥秘,不仅从基础讲起,还将通过一系列详尽案例和扩展讨论,展现其在实际开发中的无限可能......