当前位置: 首页 > news >正文

Java中的锁详解说明

转自:

Java中的锁详解说明

下文笔者讲述java中锁的详解,如下所示:

java锁简介

锁与synchronized同步块具有同样的功能:是一种线程同步机制
但锁比Java中的synchronized同步块更复杂
------------------------------------------------------------------------------------------
因为锁是由synchronized同步块的方式实现的

一个简单的锁简介说明

public class Counter{
    private int count = 0;
    public int inc(){
        synchronized(this){
            return ++count;
        }
    }
}

以上的代码中使用了synchronized(this)代码块
可保证在同一时间只有一个线程可运行return ++count
下文将使用Lock代替synchronized达到了同样的目的

public class Counter{
    private Lock lock = new Lock();
    private int count = 0;
    public int inc(){
        lock.lock();
        int newCount = ++count;
        lock.unlock();
        return newCount;
    }
}

lock()方法会对Lock实例对象进行加锁
因此所有对该对象调用lock()方法的线程都会被阻塞
直到该Lock对象的unlock()方法被调用

Lock类的实现

public class Counter{
public class Lock{
    private boolean isLocked = false;
    public synchronized void lock()
        throws InterruptedException{
        while(isLocked){
            wait();
        }
        isLocked = true;
    }

    public synchronized void unlock(){
        isLocked = false;
        notify();
    }
}
--------代码中的 
 while(isLocked)循环,称之为“自旋锁”

当isLocked为true时,调用lock()的线程在wait()调用上阻塞等待
为防止该线程没有收到notify()调用也从wait()中返回(也称作虚假唤醒),
这个线程会重新去检查isLocked条件以决定当前是否可以安全地继续执行还是需要重新保持等待,
而不是认为线程被唤醒了就可以安全地继续执行了
当isLocked为false,当前线程会退出while(isLocked)循环,并将isLocked设回true,让其它正在调用lock()方法的线程能够在Lock实例上加锁

当线程运行完毕临界区(lock()和unlock()之间)的代码后,会调用unlock()
运行unlock()会重新将isLocked设置为false
并且通知(唤醒)其中一个(若有的话)在lock()方法中调用了wait()函数而处于等待状态的线程。

锁的可重入性

Java中的synchronized同步块是可重入的
这意味着如果一个java线程进入了代码中的synchronized同步块
并因此获得了该同步块使用的同步对象对应的管程上的锁
那么这个线程可以进入由同一个管程对象所同步的另一个java代码块

public class Reentrant{
    public synchronized fun1(){
        fun2();
    }

    public synchronized fun2(){
        //
    }
}

此处的fun1()和fun2()都被声明为synchronized,
Java中和synchronized(this)块等效
当一个线程调用了fun1()
在fun1()里调用fun2()就没有什么问题
因为这两个方法(代码块)都由同一个管程对象("this")所同步

下面的代码为不可重入锁

public class Reentrant2{
    Lock lock = new Lock();
    public outer(){
        lock.lock();
        inner();
        lock.unlock();
    }

    public synchronized inner(){
        lock.lock();
        //业务代码
        lock.unlock();
    }
}
/*
运行outer()的线程首先会锁住Lock实例,当继续调用inner()。inner()方法中该线程将再一次尝试锁住Lock实例,此时该操作会失败(也就是说该线程会被阻塞),
因为这个Lock实例已经在outer()方法中被锁住了
由于两次lock()之间没有调用unlock(),第二次调用lock就会阻塞
*/
 
/*Lock类可重入性的调整示例分享*/

public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;

    public synchronized void lock()
        throws InterruptedException{
        Thread callingThread =Thread.currentThread();
        while(isLocked && lockedBy != callingThread){
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = callingThread;
  }

    public synchronized void unlock(){
        if(Thread.curentThread() == this.lockedBy){
            lockedCount--;

            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }
}

以上代码中的while循环(自旋锁)已经考虑到已锁住该Lock实例的线程
当同一个线程重复对一个锁对象加锁的次数
当unlock时,则减少锁定的次数,直到锁次数为零时,则解锁

相关文章:

  • GPIO相关介绍
  • 软件工程、软件生命周期、软件定义阶段、需求的层次/特征、概要设计、详细设计
  • 台式机电源更换笔记
  • 从文件资源管理器中隐藏文件
  • # Maven错误Error executing Maven
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (2020)Java后端开发----(面试题和笔试题)
  • lt;JVM调优gt;为什么内存过大?
  • InputMismatchException异常
  • 定时器及案例
  • 代谢组学研究的十大误区——误区十
  • 微服务项目:尚融宝(8)(后端接口:积分等级CRUD)
  • 《用Go语言自制解释器》之第4章 扩展解释器
  • SQL每日一练(牛客新题库)——第9天:检索数据
  • JQuery系列之事件切换
  • Android Studio:GIT提交项目到远程仓库
  • angular组件开发
  • Electron入门介绍
  • Spring Cloud Feign的两种使用姿势
  • tab.js分享及浏览器兼容性问题汇总
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 关于for循环的简单归纳
  • 官方解决所有 npm 全局安装权限问题
  • 前端面试之闭包
  • 王永庆:技术创新改变教育未来
  • 移动端解决方案学习记录
  • 异步
  • 原生 js 实现移动端 Touch 滑动反弹
  • 自制字幕遮挡器
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • Spring Batch JSON 支持
  • 如何在招聘中考核.NET架构师
  • # 达梦数据库知识点
  • $forceUpdate()函数
  • (39)STM32——FLASH闪存
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (python)数据结构---字典
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Core 项目指定SDK版本
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET MVC第五章、模型绑定获取表单数据
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .net6使用Sejil可视化日志
  • .NET连接数据库方式
  • .NET中winform传递参数至Url并获得返回值或文件
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?