synchronized的功能的扩展:重入锁

简介: synchronized的功能的扩展:重入锁

重入锁

重入锁可以说是synchronized,Object.wait(),Object.notify()的一种替代品。

在JDK5的早期版本,重入锁的新能要比synchronized好很多,在JDK6后对synchronized进行可很多优化,使得他和重入锁的性能差距并不大。

重入锁使用java.util.concurrent.locks.ReentrantLock类实现,下面我么来看下重入锁的简单使用案例:

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
public class ReenterLock implements Runnable {
    public static ReentrantLock lock=new ReentrantLock();
    public static int i=0;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int j=0;j<10000000;j++) {
            lock.lock();
            try {
                i++;
            }finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        ReenterLock tl=new ReenterLock();
        Thread t1=new Thread(tl);
        Thread t2=new Thread(tl);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }

}

运行程序可以得到结果为20000000.

重入锁具有很高的灵活性,需要开发人员手动用lock()与unlock()函数来指定何时加锁何时解锁,但是需要注意的是,在离开临界区的时候要记得释放锁,否则其他线程就没有机会在访问临界区了。(之所以叫重入锁是因为这种锁可以反复进入,但是记得一个线程同时获得多少锁,也必须释放相同的次数)

重入锁除了使用上的灵活性,还有一些高级的功能。

中断响应

对于synchronized来说,如果一个线程在等待锁,那么结果只有两种情况,要么获得锁继续执行,要么保持等待。但是使用重入锁。则提供了另外一种可能,就是线程可以被中断。也就是说,在等待锁的过程中,线程可以取消对锁的请求。有些时候这么做是很有必要的,比如和好朋友约好去打球,等了半小时没到,街道电话得知朋友临时有事,不能来了,那么就打道回府了。这种情况对于处理死锁有一定的帮助。使用lockInterruptibly()函数表示重入锁可以响应中断。

锁申请限时等待

除了等待外部通知外,要避免死锁还有一种办法,就是限时等待。我么可以通过tryLock方法进行一次限时的等待。

try{
    if(lock.tryLock(5,TimeUnit.SECONDS)){
        Thread.sleep(6000);
        }else{
            System.out.println("get lock failed");
        }
    }catch(InterruptdeException e){
        e.printStackTrace();
    }finally{
    if(lock.isHeldByCurrentThread()) lock.unlock();}
}

上面代码中,设置的5秒的限时等待,由于睡眠了6秒,或导致请求锁失败。
tryLock也可以不带参数进行运行,这种情况下,线程会尝试获得锁,如果锁未被其他线程占用,申请锁成功,返回true,否则申请失败,线程也不会进行等待,直接返回false。

公平锁

大多数情况下锁是不公平的,也就是说不一定先请求就先获得锁,使用synchronized关键字实现锁,锁就是不公平的,重入锁可以实现公平锁,避免现象,也就是说,只要你排队,就能获得锁,但是由于需要维护一个有序队列,导致公平锁的实现成本比较高,性能相对也非常低下。重入锁有如下一个构造函数:
public ReentrantLock(boolean fair)
当参数为true时锁是公平的的。

重入锁的好搭档:Condition条件

Condition与Object.wait(),Object.notify()方法的作用大致相同,只不过是用来与重入锁相关联的。通过Lock接口(出入锁就实现乐这一接口)的Condition newCondition()方法可以生成与当前重入锁对象绑定的Condition实例,利用Condition对象,我们可以让线程在特定的时刻进行等待,或者在某一个特定的时刻得到通知,继续执行。
Condition接口提供的方法如下。

void await() throws InterrupttedExceptionI;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterrupttedExceptionI;
boolean await(long time,TimeUnit unit) throws InterrupttedExceptionI;
boolean  awaitUntil(Date deadline)  throws InterrupttedExceptionI;
void signal();
void siganlAll();

以上个方法的含义如下:

  • await()方法会使当前线程等待,同时会释放锁,当其他线程中使用signal()或signalAll()方法的时候,线程会重新获得锁继续执行。或者线程被中断是也能跳出等待。
  • awaitUninterruptibly()方法与await()方法基本相同,但是他不会在等待过程中相应或者相应中断。
  • signal()用于唤醒一个在等待中的线程,同理signalAll()用于唤醒所有在等待中的线程。
相关文章
|
监控 物联网 视频直播
流量卡类型及其适用场景
不同流量卡的使用场景可以根据其特点、套餐内容、价格以及用户的具体需求来划分。以下是一些常见的流量卡类型及其适用场景:
|
传感器 机器学习/深度学习 数据采集
2022年第十一届认证杯数学中国数学建模国际赛小美赛:C 题 对人类活动进行分类 建模方案及代码实现
本文提供了2022年第十一届认证杯数学中国数学建模国际赛小美赛C题"对人类活动进行分类"的建模方案和Python代码实现,包括数据预处理、特征提取、LSTM网络模型构建和训练评估过程。
406 11
2022年第十一届认证杯数学中国数学建模国际赛小美赛:C 题 对人类活动进行分类 建模方案及代码实现
|
9月前
|
数据采集 API 开发工具
从 0 到 1 掌握鸿蒙 AudioRenderer 音频渲染:我的自学笔记与踩坑实录(API 14)
本文详细介绍了在 HarmonyOS 中使用 AudioRenderer 开发音频播放功能的完整流程。从环境准备(SDK 5.0.3、DevEco Studio 5.0.7)到核心概念(状态机模型、异步回调),再到开发步骤(实例创建、数据回调、状态控制),结合代码示例与常见问题解决方法,帮助开发者掌握 AudioRenderer 的底层控制与定制化能力。同时,文章还提供了性能优化建议(多线程处理、缓冲管理)及学习路径,附带官方文档和示例代码资源,助你快速上手并避开常见坑点。
368 7
|
设计模式 开发者 Python
Python编程中的设计模式:从入门到精通####
【10月更文挑战第14天】 本文旨在为Python开发者提供一个关于设计模式的全面指南,通过深入浅出的方式解析常见的设计模式,帮助读者在实际项目中灵活运用这些模式以提升代码质量和可维护性。文章首先概述了设计模式的基本概念和重要性,接着逐一介绍了几种常用的设计模式,并通过具体的Python代码示例展示了它们的实际应用。无论您是Python初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和实用的技巧。 ####
|
开发工具
centos8 yum安装mysql8 流程配置
centos8 yum安装mysql8 流程配置
1093 0
|
测试技术 持续交付 UED
软件测试的价值
软件测试的价值
246 0
|
JavaScript
Pure Admin框架学习笔记---1 (认识它)
Pure Admin框架学习笔记---1 (认识它)
958 0
|
算法
雪花算法id生成器
雪花算法id生成器
452 0
|
SQL 存储 分布式计算
Apache Impala(demo)
Apache Impala(demo)
253 0
|
JavaScript 数据安全/隐私保护 网络架构
Vue Router最佳实践,以确保你的Vue.js应用的路由管理清晰、可维护和高效
以下是使用Vue Router的最佳实践,以确保你的Vue.js应用的路由管理清晰、可维护和高效。
622 0