java锁

故意养只喵叫顺儿      2022-05-17     556

关键词:

前言

JAVA中常用的锁其实是有很多的,但是,一般来说我们常见到的可能就是几种

下面用一个图来简单表示一下

下面来简单介绍一下

一,synchronized

synchronized关键字的用法有很多,最常用的可能就是在一个方法上加上这个关键字,然后就锁住了,那么它的原理是什么呢?

我们知道JAVA对象其实分为对象头,对象体,对齐填充。

先解释一下这三个东西

1,对象头

这里面有什么东西呢?都是一些隐性的必须品

你一个对象要放在内存,你要有地址吧?那么有个东西叫内存地址,也就是哈希码

你一个对象是哪个线程的,你要知道吧?那么有个东西是threadId。

你一个对象有锁吧?那么有个东西是锁

你一个锁有状态吧?那么有个东西是锁状态

你一个对象要GC吧?那么又个东西叫GC标志

等等。

2,对象体

你一个对象有数据吧?都在里面

3,对齐填充

这玩意儿其实就是对齐用的,相信大家学JAVA的时候都学过基本数据类型int,long什么的,他们占多少字节,对吧?这东西,大家学过,但是很容易就忘记了,因为敲代码没什么用。那么一个对象占多少字节呢?

一般来说是8的倍数,那么对齐填充就是来补位的。也就是对象头+对象体+对齐填充=n*8。

 

在对象头里有个东西叫Monitor,synchronized能锁住,其实就是靠这个东西。

那么加了锁,就要释放,那么释放又是什么呢?是由JVM来做的。

synchronized的底层其实是什么呢,其实是Mutex,这个东西是什么呢?大家都知道JVM是C和汇编弄出来的。Mutex其实是这个层面的东西,比如对应在汇编里有个东西叫tsl(大家百度一下)。

那么一个synchronized的执行过程大概是什么呢?

1. 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁

2. 如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1

3. 如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。

4. 当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁

5. 如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。

6. 如果自旋成功则依然处于轻量级状态。

7. 如果自旋失败,则升级为重量级锁。

 

二,AQS

这玩意儿叫同步器,一般来说,你写代码的时候,没碰过这东西。因为这是个父类,但是你写多线程的时候肯定用过它的实现类,比如ReentrantLock;Countdownlatch等。这两个东西怎么用就不说了。

他们的底层实现都是AQS。

复杂的源码分析就不说了。

简单点说就是下面这个图

 

AQS就是个链表构成的队列加上volatile关键字。

在AQS中有个属性

private volatile int state;

举个例子

单线程的时候

假设state=0,你用ReentrantLock的时候,锁住了一个方法,当一个线程来的时候进入队列,state变成了1,OK,方法往下走,走完了state=0,没问题。

多线程的时候:

假设state=0,你用ReentrantLock的时候,锁住了一个方法,当N个线程进来的时候进入队列,队列里第一个线程拿到了锁,state变成了1,OK,方法往下走;队列里第二个线程去拿锁,发现state=1,失败了,就等待,后面的可以简单认为也是这样。当第一个线程走完了,释放了锁,出队列了;第二个线程变成第一个了,拿到了锁,那么第二个就执行,以此类推。

 

三,CAS

这个玩意儿,一般来说,写代码的时候,你应该是没有用过的。如果你用IDEA,用了lambda表达式的流处理并且想改变里面的int一类类型的值的话,IDEA会提示你用AtomicInteger或数组。

AtomicInteger(原子类)这一类的东西底层就是CAS,中文就是比较和交换。他的底层是啥呢?

 

volatile,要了解这个东西,其实要知道JVM的线程模型,如下图

 

JVM的线程模型和操作系统是对应的,当一个线程过来的时候是需要到主存里去拿东西的。

举个例子

单线程的时候:

在主存里有X,线程A要修改X,那么来拿X,拿到之后,把X记录在线程A里,然后把X修改成Y,完了以后,就有2个东西了,一个X(旧),一个是X(新),现在要把X(新)放回主存,那么就要先拿X(旧)和主存里的X比较一下,看看是不是一样的,如果是就把主存里的X变成X(新),如果不是一样的,就失败了。

多线程的时候:

在主存里有X,线程A要修改X,线程B也要修改X,那么都来拿X,拿到之后,A把X记录在线程A里,B把X记录在线程B里,然后A把X修改成Y,B把X修改成Z,完了以后,就都有2个东西了,一个X(旧),一个是X(新),现在要把X(新)放回主存,那么就要先拿X(旧)和主存里的X比较一下,看看是不是一样的,如果是就把主存里的X变成X(新),如果不是一样的,就失败了,那么A和B肯定会有一个成功一个失败。

 

怎么样?是不是有点熟悉的感觉。CAS这个东西简单点说就是乐观锁 。

这里提一下,在内存里有个东西叫缓存一致性协议,这个东西其实是volatile能实现的原因。

 

下面还有一些经常听见,但是其实你模糊的一些锁

1,自旋锁

这玩意其实是个优化功能,你写代码是不会写到它的,都是源码实现的。就是线程的唤醒,休眠什么的耗性能,所以弄了个这个东西出来,他是怎么实现的呢?其实就是for循环。。。

2,偏向锁

这玩意其实也是个优化功能,你写代码是不会写到它的,都是源码实现的。就是一个锁,第一个线程进来的时候,会记录一下这个线程,如果下一个也是他的话,就会比较快。。。

3,可重入锁

这玩意,你写代码是不会写到它的,都是源码实现的。其实就是一个线程拿到锁之后,他自己还可以拿第二次,第三次。。。代码的原理其实是有一个status的值记录一下,拿一次就+1,用完了就-1,再底层一点就是有个东西叫程序计数器。。。

4,乐观锁

CAS

5,悲观锁

synchronized

java_锁

乐观锁悲观锁独占锁共享锁阻塞算法非阻塞算法自旋锁AQSCLH队列锁MCS队列锁Ticket队列锁SMPNUMACASABA问题原子变量:AtomicReferenceAtomicIntegerAtomicReferenceFieldUpdater  查看详情

最全java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

在Java并发场景中,会涉及到各种各样的锁,比如:高并发编程系列:4种常用Java线程锁的特点,性能比较、使用场景,这些锁有对应的种类:公平锁,乐观锁,悲观锁等等,这篇文章来详细介绍各种锁的分类:公平锁/非公平锁... 查看详情

java有什么锁

Java有什么锁类型?答:自旋锁,读写锁,CAS操作,CAS的ABA问题,锁膨胀问题。你知道哪些锁?我:不就synchronized一种锁吗?(我好像曲解了她的意思)然后synchronized对应有三种锁状态:偏向锁、轻量级锁、重量级锁 syn锁,jvm里... 查看详情

java锁机制

公平锁/非公平锁可重入锁独享锁/共享锁互斥锁/读写锁乐观锁/悲观锁(实现秒杀的一种解决方案)(select*fromproductpwhere p.type=’xxxxx’ forupdate)分段锁偏向锁/轻量级锁/重量级锁自旋锁这些分类并不是全是指锁的状态... 查看详情

(转)java并发对象锁类锁私有锁

转自:http://ifeve.com/java-locks/建议参考:http://www.zhihu.com/question/28113814Java类锁和对象锁实践感谢[jiehao]同学的投稿,投稿可将文章发送到[email protected]类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行... 查看详情

java多线程--“锁”总览

根据锁的添加到Java中的时间,Java中的锁,可以分为"同步锁"和"JUC包中的锁"。同步锁  即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。Java1.0版本中就已经支持同步锁了。  同步锁的原理... 查看详情

java核心---线程进阶(代码片段)

...的synchronized(独占锁)锁优化(锁消除)java.util.concurrent包下的常见类信号量计数器CountDownLauth循环屏障乐观锁VS悲观锁乐观锁:(CAS 查看详情

java多线程之内置锁与显示锁

Java中具有通过Synchronized实现的内置锁,和ReentrantLock实现的显示锁,这两种锁各有各的好处,算是互有补充,今天就来做一个总结。Synchronized内置锁获得锁和释放锁是隐式的,进入synchronized修饰的代码就获得锁,走出相应的代码... 查看详情

java并发编程:synchronized底层优化(偏向锁轻量级锁)

Java并发编程系列:Java并发编程:核心理论 Java并发编程:Synchronized及其实现原理Java并发编程:Synchronized底层优化(轻量级锁、偏向锁)Java并发编程:线程间的协作(wait/notify/sleep/yield/join)Java并发编程:volatile的使用及其原理... 查看详情

java的读写锁

...分为读和写两种场景,即我们期望写入排他,读取共享。Java由此提供了包转后的读写锁工具类。//创建对象ReadWriteLockreadWriteLock=newReentrantReadWriteLock();//创建写锁readWriteLock.writeLock().lock();//解锁readWriteLock.writeLock 查看详情

java并发编程——锁相关java内存模型volatilecas原子操作类线程池(代码片段)

Java并发编程(二)——锁相关、Java内存模型、volatile、CAS、原子操作类、线程池一、Java锁相关1.1悲观锁和乐观锁1.2公平锁和非公平锁1.3死锁(重点)1.4独占锁(写锁)和共享锁(读锁)1.5自旋锁&#x... 查看详情

java:java学习笔记之锁机制的简单理解和使用(代码片段)

锁机制的简单理解和使用锁机制1、背景2、定义3、锁的种类4、乐观锁VS悲观锁4.1、悲观锁4.2、乐观锁4.3、举例说明4.4、CAS算法4.4.1、CAS使用4.4.2、CAS缺点4.4.3、总结5、自旋锁VS适应性自旋锁5.1、自旋锁5.2、适应性自旋锁5.3、总结6... 查看详情

java中锁分类

锁的分类大致如下:公平锁/非公平锁可重入锁/不可重入锁独享锁/共享锁乐观锁/悲观锁分段锁1、公平锁/非公平锁公平锁就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。默认情况... 查看详情

java-锁的种类及详解(代码片段)

...乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(CompareandSwap比较并交换,属于计算机底层的CPU原子操作)实现的。悲观锁:总是假设最坏... 查看详情

java并发编程——深入理解自旋锁

...有执行任何有效的任务,使用这种锁会造成busy-waiting。2.Java如何实现自旋锁?先看一个实现自旋锁的例子,java.util.concurrent包里提供了很多面向并 查看详情

java并发---锁

...         一张图了解一下java锁. 各种锁为什么要设置锁的等级jdk1.6对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向 查看详情

最全java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类:公平锁/非公平锁可重入锁独享锁/共享锁乐观锁/悲观锁分段锁自旋锁01.乐观锁vs悲观锁乐观锁与悲观锁是一种广义上的概念... 查看详情

java中的锁

...获取锁。有可能,会造成优先级反转或者饥饿现象。对于JavaReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。对于Synchronized而言,也是一种非公平锁。由于其并不... 查看详情