首页 > 编程语言 >Java锁的思想和区别

Java锁的思想和区别

时间:2024-02-23 17:14:22浏览次数:30  
标签:重入 Java 思想 区别 线程 轻量级 自旋 操作 偏向

乐观锁 VS 悲观锁

乐观锁和悲观锁是两种处理并发访问的不同策略,用于确保多个操作不会同时修改同一资源而导致数据不一致的问题。它们的区别在于处理并发时的思想和实现方式:

乐观锁:

思想:认为在大多数情况下,读操作远远多于写操作,因此假设在绝大多数情况下并发冲突是不会发生的,直到出现实际冲突才会进行处理。
实现方式:通常使用版本号(Version)或时间戳(Timestamp)来实现。在读取数据时,会将版本号或时间戳一同读取并保存,在更新数据时,会比较更新前后的版本号或时间戳是否一致,如果一致则更新成功,否则更新失败需要进行重试或其他处理。

悲观锁:

思想:认为并发冲突是常态,因此在操作数据之前会先加锁,确保同一时间只有一个操作可以访问数据,其他操作需要等待。
实现方式:通常使用数据库的行级锁或者程序中的同步锁(如Java中的synchronized关键字)来实现。在读取或更新数据之前会先获取锁,操作完成后再释放锁。
总的来说,乐观锁适合读操作频繁、冲突概率低的场景,可以减少锁的竞争,提高并发性能;而悲观锁适合写操作频繁、冲突概率高的场景,可以确保数据的一致性。

无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

在Java中,锁的升级过程包括从无锁状态到偏向锁、偏向锁到轻量级锁、轻量级锁到重量级锁的过程。以下是这些过程的简要描述:

无锁到偏向锁:

当一个线程第一次访问同步代码块时,会尝试获取偏向锁。
如果获取成功,则标记为偏向锁,锁的标记会指向获取偏向锁的线程ID。
如果获取失败,则表示有竞争,不会立即升级为偏向锁,而是会进入自旋锁或者直接升级为轻量级锁,具体取决于具体实现。

偏向锁到轻量级锁:

当有另一个线程尝试获取被偏向的锁时,会尝试升级为轻量级锁。
升级为轻量级锁时,使用CAS操作将对象头中的偏向锁标志位清除,并将锁的标记指向锁记录(Lock Record)的地址。
如果CAS操作失败,表示有竞争,则会进入自旋锁或直接升级为重量级锁。

轻量级锁到重量级锁:

当一个线程自旋等待轻量级锁的过程中,如果自旋超过一定的次数或者有其他线程尝试获取锁,则会升级为重量级锁。
升级为重量级锁时,会使用操作系统的互斥量来实现锁,将对象头中的标记置为指向重量级锁的指针,并阻塞当前线程,让其他线程竞争锁。

自旋锁:

在上述升级过程中,为了避免线程频繁地阻塞和唤醒,会使用自旋锁来在一定程度上减少线程的阻塞时间。
自旋锁会在尝试获取锁时,循环检查锁是否可用,避免线程阻塞。当自旋超过一定次数或者其他线程来竞争锁时,会放弃自旋,使用其他方式来处理。

可重入锁 VS 不可重入锁

可重入锁(Reentrant Lock)是指同一个线程在持有锁的情况下,可以重复地对同一个锁进行加锁操作而不会产生死锁。这种锁机制允许线程在持有锁的情况下多次进入同步代码块,而不会被自己持有的锁所阻塞。可重入锁的特点有助于简化编程模型,并提高了线程的灵活性和性能。

与之相对应,非可重入锁则不允许同一个线程在持有锁的情况下再次对同一个锁进行加锁操作,否则会导致死锁。

可重入锁通常使用一个计数器来记录当前线程持有锁的次数,当计数器为0时表示锁未被持有,可以被其他线程获取。

标签:重入,Java,思想,区别,线程,轻量级,自旋,操作,偏向
From: https://www.cnblogs.com/jietang64/p/18029962

相关文章

  • Javascript/DOM:如何删除 DOM 对象的所有事件侦听器
    Javascript/DOM:如何删除DOM对象的所有事件侦听器一、重写重写EventTarget添加监听事件方法addEventListenerif(EventTarget.prototype.original_addEventListener==null){EventTarget.prototype.original_addEventListener=EventTarget.prototype.addEventList......
  • Java语法之HelloWorld!
    HelloWorld入门随便新建一个文件夹(coed),存放代码新建一个Java文件文件后缀名为.JavaHello.java编写代码publicclassHello{ publicstaticvoidmain(String[]args){ System.out.print("Hello,World!"); }}编译javacjava文件,会生成一个class文件运......
  • 什么是Java中的SPI机制
    SPI,全称ServiceProviderInterface,是Java中提供的一种服务发现机制它允许应用程序动态地加载和使用第三方提供的服务实现,而无需在代码中引用这些实现类。JavaSPI是基于接口编程思想的具体体现,通过将服务接口和其实现分离,从而具备更好的可扩展性和可维护性如何定义一个Java......
  • Java事件侦听器学习记录
    前言我们监听事件之前要有事件源source,创建事件源(Event),发布事件(publishEvent),然后才能到监听事件。事件驱动机制是观察者模式(称发布订阅)具体实现,事件对象(Event)相当于被观察对象(Subject),事件监听(EventListener)相当于观察者(Observer)1、包结构(个人): 2、创建事件源(Event)......
  • java面向对象之封装-抽象-继承-组合-多态五种概念一网打尽
    说明曾经在学习java面向对象时,你是否会为面向对象的封装-继承-抽象-多态-组合等各种概念搞得稀里糊涂,乃至反复阅读,背诵其相关概念,结果一段时间过后又还给了时间。。。这种经历简直令人发指,让人无法忍受,难道就没有哪个地方能把它一次说清楚,老百姓看了以后纷纷醍醐灌顶,不再重蹈覆......
  • mysql面试高频问题---事务undo log和redo log的区别
    事务undolog和redolog的区别1.问题undolog和redolog都是mysql的日志文件,但是功能不一样。缓冲池(bufferpool):主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),以一定频率刷新到磁......
  • continue和break的区别
    continue和break的区别主要体现在它们在循环语句中的作用和用法上。以下是它们的主要区别:作用不同。break用于完全结束一个循环,跳出循环体执行循环后面的语句;continue用于终止本次循环,接着还执行后面的循环。使用场景不同。break通常用于当循环中的某些条件被满......
  • java中 break和continue区别
    breakcontinue◆break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环不执行循环中剩余的语句。(break语句也在switch语句中使用)◆continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句接着进行下一次是否执行循环的判......
  • java的基本循环结构之For循环
    1、For循环虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句--for循环,使一些循环结构变得更加简单。◆for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。◆for循环执行的次数是在执行前就确定的。语法格式如下:for(初始化;布尔表......
  • python调用Javascript实践
    一、背景知识1、Node.jsjavacript的运行环境有两个:浏览器、node.jsNode.js是一个开源与跨平台的JavaScript运行时环境。它是一个可用于几乎任何项目的流行工具!Node.js在浏览器外运行V8JavaScript引擎(GoogleChrome的内核)。这使Node.js表现得非常出色。运行js的命......