首页 > 编程语言 >java多线程-锁的介绍

java多线程-锁的介绍

时间:2024-07-02 17:28:05浏览次数:3  
标签:加锁 java Synchronized ReentrantLock 介绍 线程 2.1 多线程

多线程中常用锁

一、锁的概念

在多线程中,有乐观锁、悲观锁等很多锁的概念,在了解锁的概念之前我们需要先知道线程和进程以及纤程的概念。
可以结合JAVA多线程页面一块来看。

锁(Lock)是多线程中实现线程同步和互斥的机制。 它可以用来确保在多个线程访问共享资源时的数据一致性和安全性。

在多线程环境下,当多个线程同时访问共享资源时,可能会出现数据竞争的问题,导致程序的行为不确定或产生错误。(比如脏读)
为了避免这种情况,可以使用锁来保护共享资源,使得在任意时刻只有一个线程可以访问共享资源。

二、锁的类型

2.1 互斥锁(也称排它锁)

在访问共享对象之前,对其进行加锁操作。在访问完成之后进行解锁操作。加锁后,其他试图加锁的线程会被阻塞,直到当前线程解锁。解锁后,原本等待状态的线程变为就绪状态,重新竞争锁。

2.1.1 Synchronized和Lock

Synchronized是jvm内置锁而Lock 属于java类,Synchronized不需要处理异常状态下的锁释放,当资源使用完毕后或连接断开时自动释放锁,而 Lock 需要显示调用释放锁,Lock 接口提供了更多可适配的类和方法,包括非公平锁、读写锁等

2.1.2 ReentrantLock(可重入锁)

可重入锁也称递归锁是一种递归无阻塞的同步机制。当外层函数获得锁之后,内层递归函数仍然有获取锁的代码。ReentrantLock和Synchronized都是可重入锁,并且都是同步方式加锁。

Synchronized和ReentrantLock的区别

ReentrantLock 是类实现加锁,使用tryLock() 尝试获取锁,避免死锁,更安全;需要考虑异常情况,当是异常的时候需要在finally代码块中释放锁,ReentrantLock自己提供了加锁解锁功能,在特殊情况下加锁解锁需要借助Condition实现,ReentrantLock加锁的颗粒度比Synchronized更细,使用起来也更方便。

但是Synchronized是JDK内部实现通过关键词加锁,存在死锁问题,不需要考虑异常情况,Synchronized需要Object提供的 wait(),notify() 方法在特殊条件下来实现对方法和代码块的加锁解锁。

注意:static ReentrantLock lock = new ReentrantLock(true);
参数为true 是公平锁,false 是非公平锁

2.1.3 公平锁

公平锁即根据 先进先出 规则,从等待队列中取出第一个等待线程获取锁。
在并发环境下,每个线程在获取锁时会先查看此锁维护的等待队列,如果是空,或者当前线程是等待队列的第一个,就占有锁,否则会将自己加入到等待队列中。

2.1.4 非公平锁

可以通过 nonfairTruAcquire() 实现;与非公平锁相反,非公平锁下,新来的线程在一上来就会尝试直接占有锁,如果这时候刚好在发出请求时所变成可用状态,则这个锁会跳过队列中的等待线程,直接获得锁,否则,将自己加入到队列中。

2.1.5 中断锁

可中断锁即等待锁的过程是可以中断的。在互斥锁中,synchronized 是不可中断所,而 Lock 是可中断锁。
ReentrantLock 中提供了两种方法来中断等待操作
(1)通过tryLock方法中断
可以通过设置超时时间 timeout 以及单位 unit,在等待指定时间后,若还没有获取锁,则中断锁
(2)通过lockInterruptibly 方法
lockInterruptibly 调用后,就会马上主动中断等待,并抛出 InterruptedException 异常

2.2 共享锁

共享锁:允许多个线程共同访问资源

2.3 读写锁

java并发包提供了读写锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁。

三、悲观锁和乐观锁

3.1 悲观锁

互斥锁、自旋锁、读写锁都属于悲观锁,悲观锁认为并发访问共享资源时,冲突概率可能非常高,所以在访问共享资源前,都需要先加锁。

悲观锁适用于写多读少的情况,在多写的情况下冲突经常发生,需要用锁来保证变量修改的有序性

3.2 乐观锁

如果并发访问共享资源时,冲突概率非常低的话,就可以使用乐观锁,它的工作方式是,在访问共享资源时,不用先加锁,修改完共享资源后,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作

乐观锁适用于读多写少的情况,即冲突很少发生的时候,省去了锁的开销,增大了吞吐量

乐观锁的实现一般是CAS算法和版本控制

3.3 CAS算法

CAS 全称(Compare And Swap
比较和交换),是一种无锁算法,可以在不适用锁的情况下实现多线程间变量的同步java.util.concurrent包中的原子类就是通过CAS来实现了乐观锁。

对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

四、锁竞争

锁竞争是指多个线程试图同时访问同一个临界区(即需要互斥访问的代码区域),因此它们之间产生了竞争。在任意时刻,只能有一个线程持有锁并进入临界区,其他试图进入临界区的线程必须等待。锁竞争可能导致以下几种情况:吞吐量降低、响应时间增加、上下文切换

标签:加锁,java,Synchronized,ReentrantLock,介绍,线程,2.1,多线程
From: https://blog.csdn.net/qq_15740137/article/details/140128364

相关文章

  • (Java)知其然且知其所以然系列4
    写在开头本系列内容主要涵盖我在深入学习Java过程中对一些知识点的深入理解和巩固。如果内容表达不准确或存在谬误,欢迎在评论区或私信中进行补充或指正~目录Java接口、内部类、包        接口可以继承吗?        接口继承要重写父接口的方法吗?     ......
  • 钟馗之眼ZoomEye用法介绍
    认识ZoomEyeZoomEye是一个网络空间搜索引擎,专门用于发现和分析互联网设备和服务的公开信息。它由中国安全公司Knownsec开发,广泛用于安全研究、漏洞评估和网络监控。以下是ZoomEye的主要功能介绍: 1.设备搜索ZoomEye可以扫描和搜索互联网上公开的设备,包括服务器、路由器、摄......
  • 书城在线系统:基于Java和SSM框架的高效信息管理平台
    开头语:你好呀,我是计算机学长猫哥!如果有相关需求,文末可以找到我的联系方式。开发语言:Java数据库:MySQL技术:SSM框架(Spring,SpringMVC,Mybatis)工具:MyEclipse,Tomcat,MySQL系统展示首页管理员功能模块用户功能模块前台首页功能模块摘要雅博书城在线系统,一......
  • 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-1-环境准备与搭建
    1.简介Python+Playwright系列的文章还没有结束,就有好的小伙伴或者童鞋们私信公众号留言,问宏哥什么时候出Java语言的Playwright的自动化测试文章。本来想趁热打铁将Python+Playwright完结后,就开始Java语言的Playwright的自动化测试文章,但是好多人私信留言,索性就两个系列的文章......
  • Java实现登录验证 -- JWT令牌实现
    目录1.实现登录验证的引出原因2.JWT令牌2.1使用JWT令牌时2.2令牌的组成三.JWT令牌(token)生成和校验3.1引入JWT令牌的依赖3.2使用Jar包中提供的API来实现JWT令牌的生成和校验3.3使用JWT令牌验证登录1.实现登录验证的引出传统思路下:登录页面把用户名和密码交......
  • JAVA,认识类
    一、类?什么是类?官方文档解释:类(Class)是面向对象程序设计(OOP,Object-OrientedProgramming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。拥有共同属性抽象的集合称之为类白话:简单理......
  • 数据库我是这样写出来的,Java版本1,持续更新
    了解数据库的内部原理其实很不容易,大部分的读写都停留在理论文章上,因此肖哥带着大家使用Java手写一个完整的数据库,让大家了解数据库的解析器、性能分析器、认证、查询优化器,执行引擎、存储引擎、事务管理、MVCC,数据恢复等一系列功能。这个工作量比较大,属于每日1-2更新,大家如......
  • JavaScript 中删除数组元素
    在JavaScript中,没有像Java的ArrayList中的remove方法那样直接删除指定元素的方法,删除指定下标的数组元素可以通过几种方式实现方法一:使用 splice() 方法splice()方法可以在数组中添加或删除元素,并返回被删除的元素。letarr=[1,2,3,4,5];letindexToRemove......
  • Java知识点整理 18 — Lambda表达式
    一.简介Lambda表达式是函数式编程思想的体现,强调做什么,而不是以什么方式去做。面向对象编程思想强调的是对象,必须通过对象的形式来做一些事情。比如多线程执行任务,需要创建对象,对象需要实现指定接口,然后再执行等。过程相对繁琐。而如果使用函数式编程思想,可以直接通过传递......
  • 在多线程并发操作中处理大量文件时,以下是一些关键的底层原理和技术:
    在多线程并发操作中处理大量文件时,以下是一些关键的底层原理和技术:1.文件句柄管理每个线程需要独立地管理文件句柄,文件句柄是操作系统提供的用于标识和访问文件的资源。在Windows环境下,使用CreateFile函数可以打开文件并获得文件句柄。每个文件句柄具有其自己的上下文和状态,......