JAVA多线程编程之ReentrantLock

本文深入探讨ReentrantLock的使用,对比synchronized关键字,讲解其手动释放锁、尝试锁定及响应中断的特点。通过代码示例展示公平锁与非公平锁的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ReentrantLock主要是用来替代synchronized的。

先来看一个例子:

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

public class o1reentrantlock {
		
	public static void main(String [] args){
		
		ReentrantLock lock = new ReentrantLock();
		
		m5 a = new m5();
		
		new Thread(() -> {
			try {
				lock.lock();
				for(int i=0; i<5; i++){
					a.m1();
					System.out.println(Thread.currentThread().getName()+"执行了+1,结果为:"+a.count);
					TimeUnit.SECONDS.sleep(1);
				}
			} catch (Exception e) {
				// TODO: handle exception
			} finally {
				System.out.println("释放锁!");
				lock.unlock();
			}

		},"t1").start();
		
		
		new Thread(() -> {
			try {
				lock.lock();
				for(int i=0; i<5; i++){
					a.m1();
					System.out.println(Thread.currentThread().getName()+"执行了+1,结果为:"+a.count);
					TimeUnit.SECONDS.sleep(1);
				}
			} catch (Exception e) {
				// TODO: handle exception
			} finally {
				lock.unlock();
			}
		},"t2").start();
		
	}
	
}

class m5{
	
	int count = 0;
	
	void m1(){
		this.count++;
	}
	
}

程序执行结果为;
在这里插入图片描述
来说一下这段程序:
我们创建了一把 ReentrantLock 锁 ,第一个线程拿到锁后(lock),执行五次循环打印,finnaly里释放锁,然后第二个线程拿到锁后继续执行5次循环打印,最终释放锁。

ReentrantLock 不会自动释放锁,必须必须必须手动释放锁。
synchronized 出现异常会自动释放锁,ReentrantLock 遇到异常不会释放锁,需要在finnaly()块中释放锁。一定要注意,如果稍不注意就造成死锁了。

ReentrantLock 可以进行尝试锁定,如果锁定,那我就执行,如果没拿到锁,那我就该干嘛干嘛。(就是非阻塞),并且ReentrantLock 可以指定尝试锁定超时期限,如果在规定时间内我还没有获得锁,那么继续执行。

看代码:

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

public class o1reentrantlock {
		
	public static void main(String [] args){
		
		m5 a = new m5();
		
		new Thread(() -> {
			for(int i=0; i<5; i++){
				a.m1();
			}
		},"t1").start();
		
		
		new Thread(() -> {
			for(int i=0; i<5; i++){
				a.m1();
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		},"t2").start();
	}
	
} 

class m5{
	
	int count = 0;
	
	ReentrantLock lock = new ReentrantLock();
	
	void m1(){
		boolean islock = false;
		try {
			islock = lock.tryLock();
			if(islock){
				System.out.println(Thread.currentThread().getName()+"拿到锁了!");
				this.count++;
				System.out.println("当前count值为:"+this.count);
			}else{
				System.out.println(Thread.currentThread().getName()+"没拿到锁,算拉倒!");
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(islock) lock.unlock();
		}
	}
	
}

先说一下这段程序,两个线程。各调用m1方法5次,两个线程都尝试获取锁,如果没得到就输出“”算拉倒”,那最终count值+打印的“算拉倒”应该等于10;
在这里插入图片描述

ReentrantLock 可以对interrupt时间做出反应。

看代码:

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

public class gongping {

    public static void main(String [] args){

        m a = new m();

        new Thread(() -> {
            for (int i =0; i<1000; i++){
                a.m1();
            }
        }).start();

        new Thread(() -> {
            for (int i =0; i<1000; i++){
                a.m1();
            }
        }).start();

    }




}

class m{

    ReentrantLock lock = new ReentrantLock();

    void m1(){
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName()+"执行了操作!");
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }

}

代码说明:两个线程各执行1000次打印输出。
输出很不规范,线程一一段线程二一段,而且两个线程执行时间也不同有的多有的少。(太长了,图就不贴了)
接下让我们改成公平锁执行一下

ReentrantLock lock = new ReentrantLock(true);

在这里插入图片描述
两个线程你一次我一次比较公平。

ReentrantLock默认非公平锁,可以指定公平锁,公平锁和非公平锁比较性能比较低,但是可以防止线程饿死。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值