Java锁ReentrantLock

2024-07-14 16:22

ReentrantLock

Sync是隐式锁。Lock是显示锁

ReentrantLock是Lock的默认实

概念:

1.可重入锁:可重入锁是指同一个线程可以多次获得同一把锁;ReentrantLock和关键字Synchronized都是可重入锁

2.可中断锁:可中断锁时子线程在获取锁的过程中,是否可以相应线程中断操作 synchronized 是不可中断的。ReentrantLock是可中断的

3.公平锁和非公平锁:公平锁是指多个线程尝试获取同一把锁的时候,获取锁的顺序按照线程到达的先后顺序获取,而不是随机插队的方式获取。synchronized是

非公平锁,而ReentrantLock是两种都可以实现,不过默认是非公平锁.

示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 主类ReentrantLockMain展示了使用ReentrantLock实现线程安全的工资扣除示例。
 */
public class ReentrantLockMain {
    /**
     * 工资变量,初始化为500000。此变量的修改需要线程安全的操作。
     */
    private static Integer salary = 500000;
    /**
     * 使用ReentrantLock实例作为线程同步的机制。
     */
    private static ReentrantLock lock = new ReentrantLock();
    /**
     * SalaryRunnable内部类实现了Runnable接口,用于扣除工资的线程任务。
     */
    static class SalaryRunnable implements Runnable {
        /**
         * 执行工资扣除操作。
         * 使用lock.lock()获取锁,确保在同一时刻只有一个线程可以执行工资扣除操作,
         * 以保证线程安全。
         */
        @Override
        public void run() {
            try {
                lock.lock(); // 获取锁
                salary = salary - 1000; // 执行工资扣除操作
                System.out.println("salary:"+salary);
            } catch (Exception ex) {
                System.out.println(ex.getMessage()); // 捕获并打印异常信息
            } finally {
                if(lock.isHeldByCurrentThread()) { //检查当前线程是否持有锁。
                    lock.unlock(); // 无论是否发生异常,最终都要释放锁
                }
            }
        }
    }

    /**
     * 程序入口主方法。
     * 创建一个线程池,并提交一个SalaryRunnable任务进行执行。
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool(); // 创建线程池
        for(int i=0;i<5;i++) {
            SalaryRunnable task = new SalaryRunnable(); // 创建工资扣除任务
            threadPool.execute(task); // 提交任务给线程池执行
        }
        threadPool.shutdown();
    }
}

tryLock

​ 申请锁等待限时,在获取锁的时间不确定的情况下,synchronized关键字获取锁的过程中,只能等待其他线程把锁释放之后才能够有机会获取到锁。所以获

取锁的时间有长有短,充满了不确定性。如果获取锁的时间能够设置超时时间,无法判断。

​ ReentrantLock提供了获取锁限时等待的方法 tryLock(),可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true表示获取

锁成功,false表示获取锁失败。

示例1:

import java.util.concurrent.locks.ReentrantLock;

/**
 * TryLockMain 类用于演示使用 ReentrantLock 的 tryLock 方法。
 */
public class TryLockMain {
    /**
     * 全局的 ReentrantLock 实例,用于演示线程之间的锁竞争。
     */
    private static ReentrantLock lock = new ReentrantLock();

    /**
     * T 类继承自 Thread,用于具体执行线程任务。
     */
    public static class T extends Thread {
        /**
         * 构造函数,初始化线程名称。
         *
         * @param name 线程名称。
         */
        public T(String name) {
            super(name);
        }

        /**
         * 线程的执行逻辑。
         */
        @Override
        public void run() {
            try {
                // 尝试使用 tryLock 方法获取锁。
                System.out.println("TryLock");
                if (!lock.tryLock()) { // 如果锁被占用,返回false。
                    System.out.println("获取锁失败");
                    return;
                } else {
                    System.out.println("获取锁成功");
                    // 在获取锁成功后,使用 synchronized 关键字确保线程安全。
                    synchronized (this) {
                        // 这里使用 getName() 直接打印线程名称。
                        this.getName().toString(); // 这里使用的是this.getName().toString(),而不是this.getName().toUpperCase()。
                    }
                    // 执行完任务后释放锁。
                    System.out.println(" lock.unlock()");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 确保在任何情况下都释放锁。
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
    }

    /**
     * 程序入口,创建并启动两个线程,演示锁的获取和释放。
     *
     * @param args 命令行参数。
     * @throws Exception 如果线程的等待发生异常。
     */
    public static void main(String[] args) throws Exception {
        T t1 = new T("name:T1 ");
        T t2 = new T("name:T2 ");
        t1.start();
        t2.start();
        // 等待两个线程执行完毕。
        t1.join();
        t2.join();
    }
}

示例2:

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

/**
 * TryLockMain 类用于演示使用 ReentrantLock 的 tryLock 方法。
 */
public class TryLockMain {
    /**
     * 全局的 ReentrantLock 实例,用于演示线程之间的锁竞争。
     */
    private static ReentrantLock lock = new ReentrantLock();

    /**
     * T 类继承自 Thread,用于具体执行线程任务。
     */
    public static class T extends Thread {
        /**
         * 构造函数,初始化线程名称。
         *
         * @param name 线程名称。
         */
        public T(String name) {
            super(name);
        }

        /**
         * 线程的执行逻辑。
         */
        @Override
        public void run() {
            try {
                // 尝试使用 tryLock 方法获取锁。
                System.out.println("TryLock");
                if (!lock.tryLock()) { // 如果锁被占用,返回false。
                    System.out.println("获取锁失败");
                    return;
                } else {
                    System.out.println("获取锁成功");
                    // 在获取锁成功后,使用 synchronized 关键字确保线程安全。
                    synchronized (this) {
                        // 这里使用 getName() 直接打印线程名称。
                        this.getName().toString(); // 这里使用的是this.getName().toString(),而不是this.getName().toUpperCase()。
                    }
                    // 执行完任务后释放锁。
                    System.out.println(" lock.unlock()");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 确保在任何情况下都释放锁。
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
    }

    /**
     * 程序入口,创建并启动两个线程,演示锁的获取和释放。
     *
     * @param args 命令行参数。
     * @throws Exception 如果线程的等待发生异常。
     */
    public static void main(String[] args) throws Exception {
        T t1 = new T("name:T1 ");
        T1 t2 = new T1("name:T2 ");
        t1.start();
        t2.start();
        // 等待两个线程执行完毕。
        t1.join();
        t2.join();
    }


    public static class T1 extends Thread {
        public T1(String name) {
            super(name);
        }
        @Override
        public void run() {
            try {
                System.out.println("System.currentTimeMillis(): " + "+" + this.getName() + "开始获取锁!");
                tryLock();
                if (lock.tryLock(2, TimeUnit.SECONDS)) { // lock
                    System.out.println("System.currentTimeMillis(): " + "+" + this.getName() + "获得锁!");
                    try {
                        Thread.sleep(500L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("System.currentTimeMillis(): " + "+" + this.getName() + "未能获取到锁!");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        private synchronized void tryLock() throws InterruptedException {
            while (!lock.tryLock( 2, TimeUnit.SECONDS)) { // lock
                System.out.println("System.currentTimeMillis(): " + "+" + this.getName() + "尝试获取锁中...");
            }
        }
    }

}
相关新闻
热点
投票
查看结果
Tags

站点地图 在线访客: 今日访问量: 昨日访问量: 总访问量:

© 2025 个人网站 版权所有

备案号:苏ICP备2024108837号

苏公网安备32011302322151号