首页 > 编程语言 >Java多线程:关于锁

Java多线程:关于锁

时间:2023-07-19 19:23:37浏览次数:54  
标签:加锁 Java 并发 互斥 线程 关于 多线程 优化 轻量级

目录

互斥访问资源

加锁的本质是,为了竞争一个资源访问互斥状态,保证线程安全
如果只是读,是线程安全的,因为竞态资源不会修改和数据不一致
读不需要互斥,但是读的时候不能,而写需要互斥

互斥状态的要求:atomic、volatile

原子性:互斥状态抢占后不能被中断,需要原子修改互斥状态
可见性:互斥状态必须全局同一,不能有缓存导致的数据不一致

操作系统互斥锁mutex的缺点

在sychronized锁中利用了mutex实现互斥
额外的时间开销 -- 缺点:

  • 可以优化的缺点:
    1. 管态切换,调度线程
    2. 线程上下文中断、保存与恢复,线程切换
    3. 线程阻塞
    4. 线程唤醒
  • 无法优化的缺点:
    1. 并发到串行 --> 无法改变,线程安全,就要加锁
    2. 线程创建与销毁 --> 优化:线程池-退出从销毁改为循环

偏向锁、轻量级锁、重量级锁

优化思路:

  1. 不存在线程安全问题(锁消除):
    此时不需要加锁
    如果加锁jvm会进行"锁消除"的编译层面优化
  2. 不需要竞争(偏向锁):
    此时不需要加锁,但是很难判断有没有竞争
  3. 不需要阻塞(轻量级锁):
    CAS乐观锁 / 自旋锁
    • 抢不到锁,先乐观的认为马上就能抢到锁,进行有限次重试
    • 如果有限次重试内没有抢到锁,再阻塞
    • 乐观的原因:线程任务短,可以很快释放锁
  4. 如果线程任务长(重量级锁,mutex)
    轻量级锁的重试是无用功,此时需要阻塞和唤醒
    但是其实相比于长时间的线程任务,阻塞和唤醒的时间就无足轻重了
  5. 锁升级
    如果当前并发量和任务时长增加,此时需要进行锁升级
  6. 锁膨胀:编译器增加锁的粒度

减小锁的粒度

ConcurrentHashMap:只锁当前操作的桶位,这样可以并发写入多个桶位
优化:减少锁住的部分,也可以优化锁
问题 - 锁膨胀:假如当前

共享锁-读锁、排他锁/互斥锁-写锁

最开始说过读锁和写锁,这里继续深入
继续优化:如果并发只是为了读数据,不修改资源
那么不需要对读请求串行化,可以并发读,这个就是共享锁
如果当前环境读多写少,那么并发锁设计成共享锁而非互斥锁

避免死锁的锁特性:重入锁

学习ConcurrentHashMap的锁思想

结语

加锁是为了线程安全,但是也要考虑性能
根据读写、并发量、任务时长、锁粒度、避免死锁等等进行优化

标签:加锁,Java,并发,互斥,线程,关于,多线程,优化,轻量级
From: https://www.cnblogs.com/luoyicode/p/17566521.html

相关文章

  • 页面框架 java代码
    页面框架Java代码简介在现代Web开发中,一个好的页面框架可以大大提高开发效率和代码质量。页面框架是一种提供基础结构和功能的软件库,它可以帮助开发人员快速构建和维护Web应用程序。本文将介绍Java语言中一些常用的页面框架,并提供相应的代码示例。1.SpringMVCSpringMVC是一......
  • 【后端面经-Java】JVM垃圾回收机制
    (【后端面经-Java】JVM垃圾回收机制)1.Where:回收哪里的东西?——JVM内存分配JVM垃圾回收机制(GarbageCollect,简称GC)主要负责回收JVM内存当中未被及时释放回收的内存区域,JVM垃圾回收机制让程序员摆脱了手动释放内存的操作,降低了程序员疏忽大意导致的风险。那么,垃圾回收机制到底针......
  • 兴业银行java笔试多少分过
    如何实现“兴业银行java笔试多少分过”整体流程为了实现“兴业银行java笔试多少分过”,我们需要按照以下步骤进行操作:步骤操作步骤一创建一个Java类步骤二添加一个主方法步骤三实现用户输入步骤四计算笔试成绩步骤五判断是否通过步骤六输出结果......
  • 写一篇关于数据库mysql的英语作文
    如何写一篇关于数据库MySQL的英语作文流程概述写一篇关于数据库MySQL的英语作文可以分为以下步骤:步骤描述1确定文章主题2收集和整理相关资料3规划文章结构4开始写作5逐步完善文章6进行修改和润色7完成作文步骤详解步骤1:确定文章主题首......
  • 无法将“java”项识别为
    无法将“java”项识别为?当我们在开发Java应用程序时,有时会遇到编译器报错信息:“无法将“java”项识别为”。这种错误通常表示编译器无法找到所需的Java类或接口。在本文中,我们将探讨可能导致该错误的原因,并提供解决方案。1.类路径错误Java编译器需要通过类路径来查找和加载所需......
  • 文本diff Java
    文本diffJava概述在软件开发过程中,经常会遇到需要对比两个文本文件或字符串的差异的情况。文本diff(差异)是指找出两个文本之间的增删改操作,从而得到这两个文本之间的差异。Java提供了一些库和算法来实现文本diff功能,我们可以使用它们来进行文本比较和差异分析。1.文本差异算法......
  • 【后端面经-Java】JVM垃圾回收机制
    目录1.Where:回收哪里的东西?——JVM内存分配2.Which:内存对象中谁会被回收?——GC分代思想2.1年轻代/老年代/永久代2.2内存细分3.When:什么时候回收垃圾?——GC触发条件4.Why:凭什么说它是垃圾?——垃圾判断算法4.1引用计数法4.2可达性分析法5.How:如何对待垃圾?——垃圾回收算法5......
  • 怎么看java环境
    怎么看Java环境Java环境是指Java开发和运行Java程序所需的软件和配置。它包括JavaDevelopmentKit(JDK)、JavaRuntimeEnvironment(JRE)和Java虚拟机(JVM)。在本文中,我将介绍如何查看Java环境并提供相关的代码示例。查看Java版本要查看Java环境,首先需要确定安装了Java开发工具包(JDK)......
  • 怎么遍历Java中可变数组
    如何遍历Java中的可变数组在Java中,可变数组是一种动态大小的数组,也称为动态数组或ArrayList。它可以根据需要自动调整大小,因此非常方便。遍历可变数组是经常使用的操作之一,本文将介绍如何遍历Java中的可变数组,并提供相应的代码示例。问题描述假设我们有一个可变数组,包含了一组学......
  • 怎么把java转成python
    如何将Java代码转换为Python代码在软件开发中,经常会遇到需要将一个编程语言的代码转换为另一种编程语言的代码的情况。本文将介绍如何将Java代码转换为Python代码,并使用一个实际问题来演示这个过程。假设我们需要解决一个实际的问题:给定一个整数数组,我们需要编写一个函数来计算数......