Java并发——锁(重入锁)

重入锁(ReentrantLock)是一种可重入的互斥锁,它允许同一个线程多次获取同一个锁。重入锁的特点和好处如下:

1. 可重入性:同一个线程可以多次获取同一个锁,而不会造成死锁。当一个线程已经获取了锁之后,再次获取锁时会增加锁的持有计数,只有当锁的持有计数为0时才会真正释放锁。

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();
        try {
            // 执行一些操作
            methodA();
        } finally {
            lock.unlock();
        }
    }

    public static void methodA() {
        lock.lock();
        try {
            // 执行一些操作
        } finally {
            lock.unlock();
        }
    }
}

 示例中,同一个线程在获取锁之后,可以多次调用方法methodA并再次获取锁,而不会造成死锁。这种可重入性允许线程在同一个锁的保护下执行多个相关的操作。

2. 公平性:重入锁可以通过构造函数指定锁的公平性,即等待时间最长的线程优先获取锁。这样可以避免线程饥饿现象,保证所有线程都能有机会获取锁。

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        // 创建并启动多个线程
    }

    public static void someMethod() {
        lock.lock();
        try {
            // 执行一些操作
        } finally {
            lock.unlock();
        }
    }
}

 示例中,通过在重入锁的构造函数中传入true来创建一个公平锁。这样,等待时间最长的线程将优先获取锁。这种公平性保证了所有线程都能有机会获取锁,避免了线程饥饿现象。

3. 可中断:重入锁提供了可中断的获取锁的方式。当一个线程在等待获取锁的过程中,可以通过调用interrupt方法中断自己,从而退出等待状态。

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {
                lock.lockInterruptibly();
                // 执行一些操作
            } catch (InterruptedException e) {
                // 处理中断异常
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                lock.lockInterruptibly();
                // 执行一些操作
            } catch (InterruptedException e) {
                // 处理中断异常
            } finally {
                lock.unlock();
            }
        });

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

        // 在某个时刻中断t1或t2线程
        t1.interrupt();
    }
}

 示例中,使用lockInterruptibly方法来获取锁,并通过捕获InterruptedException来处理中断异常。这样,当某个线程在等待获取锁的过程中被中断时,可以及时退出等待状态,避免线程长时间等待锁而无法响应中断。

4. 条件变量:重入锁提供了条件变量的支持,可以通过条件变量实现线程的等待和唤醒机制。通过使用条件变量,可以更灵活地控制线程的并发执行。

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

public class ConditionVariableExample {
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    private static boolean flag = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                while (!flag) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        // 处理中断异常
                    }
                }
                // 执行一些操作
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                // 执行一些操作
                flag = true;
                condition.signal();
            } finally {
                lock.unlock();
            }
        });

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

示例中,创建了一个条件变量condition,并使用它在两个线程之间进行等待和唤醒操作。线程t1在获取锁之后,进入while循环,检查条件是否满足,如果条件不满足,则调用condition.await()方法将线程进入等待状态。线程t2在获取锁之后,执行一些操作,并将条件flag设置为true,然后调用condition.signal()方法唤醒等待的线程t1。

通过使用条件变量,我们可以更灵活地控制线程的并发执行。线程可以根据条件的满足与否来决定是否等待或继续执行,从而实现线程间的协调和通信。

需要注意的是,在使用条件变量时,必须先获取锁才能调用条件变量的方法。这是因为条件变量是与锁相关联的,只有持有锁的线程才能操作条件变量。

重入锁的好处包括:

1. 灵活性:重入锁提供了更灵活的锁获取和释放方式,可以适应不同的并发场景。与synchronized关键字相比,重入锁提供了更多的功能和控制选项。

2. 性能优化:重入锁的性能通常比synchronized关键字更好。重入锁采用基于CAS操作的方式来实现锁的获取和释放,相对于synchronized关键字的互斥方式,重入锁的性能更高。

3. 可中断等待:重入锁支持可中断的等待方式,可以更好地处理线程的中断请求,避免线程长时间等待锁而无法响应中断。

总而言之,重入锁是一种功能强大且灵活的锁机制,它提供了可重入性、公平性、可中断等待和条件变量等特性,可以更好地满足不同并发场景的需求,并提供更好的性能和可靠性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值