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

【 java 多线程】同步锁 (Lock) 解决线程的安全问题

📋 个人简介

  • 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
  • 📝 个人主页:馆主阿牛🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:java 小白到高手的蜕变🍁
  • 💬格言:要成为光,因为有怕黑的人!🔥
    请添加图片描述

目录

    • 📋 个人简介
  • 前言
    • Lock锁
    • 案例
    • 面试题:synchronized与Lock的对比
    • 开发中实现线程同步的优先使用顺序:
  • 结语

前言

我们之前写博文总结了通过同步代码块以及同步方法的方式来实现线程的同步,从而解决线程的安全问题,今天我总结一下Lock锁来实现线程的同步!

Lock锁

  • 从 JDK 5.0开始, Java 就提供了更强大的线程同步机制:通过显式定义同
    步锁对象来实现同步。同步锁使用 Lock 对象充当。

  • java.util.concurrent.locks.Lock 接口是控制多个线程对共享资源进行访问的
    工具。锁提供了对共享资源的独占访问,每次只能有一个线程对 Lock 对象加锁,线程开始访问共享资源之前应先获得 Lock 对象。

  • ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是 ReentrantLock ,可以显式加锁、释放锁。

案例

我们依旧使用多窗口卖票这个经典案例。用Lock锁实现同步,解决重票错票问题。

package lock;

import java.util.concurrent.locks.ReentrantLock;

public class Demo {
    public static void main(String[] args) {
        MyTh m = new MyTh();
        Thread t1 = new Thread(m);
        Thread t2 = new Thread(m);
        Thread t3 = new Thread(m);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

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

class MyTh implements Runnable{
    private int tickets = 100;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(true){
            lock.lock(); // 调用lock()方法加锁
            try {
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName() + "-票号为:" + tickets);
                    tickets--;
                }else{
                    break;
                }
            }finally {
                lock.unlock(); // 调用unlock()方法解锁
            }
        }
    }
}

在这里插入图片描述

面试题:synchronized与Lock的对比

  1. Lock 是显式锁(手动开启和关闭锁,别忘记关闭锁), synchronized 是隐式锁,出了作用域自动释放。
  2. Lock 只有代码块锁, synchronized 有代码块锁和方法锁。
  3. 使用 Lock 锁, JVM 将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)。

开发中实现线程同步的优先使用顺序:

Lock→同步代码块→ 同步方法

结语

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门

相关文章:

  • 计算机学院第三周语法组及算法组作业
  • Java数据结构 | 二叉树的基本操作
  • IP分片--为什么单次最大传输1472个字节
  • QT中QThread的各个方法,UI线程关系,事件关系详解(5)
  • Flask-05-——(注册功能的实现,六、1将用户提交的注册数据保存在数据库 六、2 发送AJAX请求 六、3验证码的获取六、4验证码倒计时)
  • 【C++】入门(上)
  • MySQL进阶实战1,数据类型与三范式
  • TYUT太原理工大学2022需求工程考试选择题自测版
  • Xilinx selectIO 资源的使用——input方向
  • Day1——数组 二分查找、移除一个数
  • QT中QThread的各个方法,UI线程关系,事件关系详解(3)
  • RNN模型与NLP应用:文本处理与词嵌入-2
  • KVM导入Ubuntu Cloud 镜像创建虚机及调整磁盘大小
  • 【漏洞复现-骑士cms-代码执行】vulfocus/骑士cms_cve_2020_35339
  • 模拟实现优先级队列
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • ES6 学习笔记(一)let,const和解构赋值
  • HTTP 简介
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • mockjs让前端开发独立于后端
  • MySQL数据库运维之数据恢复
  • Puppeteer:浏览器控制器
  • python docx文档转html页面
  • Web Storage相关
  • windows-nginx-https-本地配置
  • 爱情 北京女病人
  • 飞驰在Mesos的涡轮引擎上
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 一个项目push到多个远程Git仓库
  • 原生 js 实现移动端 Touch 滑动反弹
  • 智能合约Solidity教程-事件和日志(一)
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • Hibernate主键生成策略及选择
  • kubernetes资源对象--ingress
  • 正则表达式-基础知识Review
  • ​Java并发新构件之Exchanger
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • ​马来语翻译中文去哪比较好?
  • #ifdef 的技巧用法
  • #Linux(权限管理)
  • #QT(串口助手-界面)
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (arch)linux 转换文件编码格式
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)jdk与jre的区别
  • (转载)Linux 多线程条件变量同步
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .gitignore文件_Git:.gitignore
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net Stream篇(六)
  • .net 受管制代码