关于AQS中的enq方法的理解

article/2025/8/28 11:46:05

自己太笨了,总感觉有点绕,就整理下吧~

private Node enq(final Node node) {//自旋锁for (;;) {//tail默认就是nullNode t = tail;if (t == null) { // Must initialize//因为tail默认是null,所以首次一定会进来//compareAndSetHead在下面//也就是首次一定会把一个新的node设置为headif (compareAndSetHead(new Node()))//tail=head=new Node()tail = head;//到这里就是tail和head都会指向new Node} else {//第二次一定进入else发//假如此时进入了一个线程A,这个A已经被封装成了node传进来//当前的node的pre指向t,也就是tail,也就是刚才创建的Node,//因为第一行就定义了Node t = tail,而t=head=nodenode.prev = t;//这里看下面的compareAndSetTail方法//把tail节点赋值为新传入的node(Thread A),赋值操作就相当于指向if (compareAndSetTail(t, node)) {//这里的t指的是原来的tail节点,tail指向一开始的new Node//所以就是new Node的next指向新传入的node(Thread A)t.next = node;return t;}}}
}private final boolean compareAndSetHead(Node update) {//当前的head字段,和null值比对,默认是null,所以相等,所以赋值为update,也就是new node()return unsafe.compareAndSwapObject(this, headOffset, null, update);
}private final boolean compareAndSetTail(Node expect, Node update) {//当前的tail字段和期望值exepct,即t进行比较,一定是相等的啊,以为t=tail么,所以更新赋值为update,//即新传进来的node(Thread A)return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}

第一次一定是进入if

在这里插入图片描述

当有新的线程进入的时候,进入else(其实没有新的线程进入还是要进入else的),红色的是else所做的操作

在这里插入图片描述

总结:

这里面head和tail都是一个node,但是这里我理解为一个类似于指针的东西,它们存在的意义也是为了维持这个双向的链表,没有实际的意义,包括prev和next也是。

还是挺绕的,感觉没必要理解这么透彻,主要思想就是

第一次进来的时候创建这个双向链表的空节点,后面传入新的节点的时候,开始往双向链表后面添加新的节点,而head和tail永远指向第一个和最后一个,中间都是一些切换指针(我这里暂且理解为指针吧,也就是赋值操作,比如tail和head的赋值,prev和next的赋值。)

for(;;)是一个自旋锁,为了不停的去尝试添加节点,但是可能存在并发问题,所以通过cas的方式,添加,可能上次被线程a抢占先机,这次自己还是要去尝试,如何进行不断的尝试?所以通过自旋锁解决,当然如果添加成果最后会通过return跳出自旋锁。

个人认为这个自旋锁和cas的操作用的很厉害,值得学习!
仔细想想为什么这么设计?
因为当前的这个compareAndSetTail和compareAndSetHead,这两个操作,简单说就是为了切换指针指向,简单说就是一“操作”,任何操作,因为在操作系统中,虽然我们目前在解决并发问题,但是也是存在并发问题的,对于这个“操作来说”。所以我们可以选择加锁,也可以选择这种cas自旋锁的方式,因为这个操作可能是很快的,因为可能同时又一万个线程都被阻塞了(极端一点的情况),这个时候,会有很多的切换指针的这个“操作”,反复的加悲观锁的话,没有cas这种乐观锁好。简单总结下,就是这种cas自旋锁的方式能提升性能。

以上全是我的个人理解,可能存在很大的问题,希望没有误导到你,如果有问题还希望您及时指出。


http://chatgpt.dhexx.cn/article/scGsdQl6.shtml

相关文章

队列等待之enq: TX - row lock contention

【性能优化】队列等待之enq: TX - row lock contention 问题背景&#xff1a; 客户反映某条sql DELETE SHAREINNERDOC WHERE SOURCEID:B1<br/>这个执行时间太长 问题解决 1> 查看awr报告&#xff1a; 有队列等待之enq: TX - row lock contention&#xff0c;对应的sq…

等待事件 enq:TX - row lock contention分析与解决

6月30日&#xff0c;数据库发生了大量锁表。大概持续1小时&#xff0c;并且越锁越多。后来通过业务人员停掉程序&#xff0c;并kill掉会话后解决。 几天后再EM上查看CPU占用&#xff1a; CPU发生了明显等待。 主要是由于enq:TX - row lock contention等待事件造成。 等待事…

java -- 随机获取字母或者数字

java只有涉及到随机的&#xff0c;最经常用到的方法就是Math.random()&#xff0c;这个方法会返回一个大于0小于1的随机数( 能取0不能取1 )&#xff0c;如果我们要随机0-9&#xff0c;就可以用&#xff08;Math.random()*10&#xff09;来表示&#xff0c;随机0-99也类似如此操…

JavaScript生成随机字母数字字符串

如何使用javascript生成随机字母数字字符串&#xff1f;下面本篇文章就来给大家介绍一下使用JavaScript生成随机字母数字字符串的方法&#xff0c;希望对大家有所帮助。 方法一&#xff1a;Math.random()方法和Math.floor()方法 ● 创建一个函数&#xff0c;该函数有两个参数…

Python - 怎么将一个数字拆分成多个随机数字

前情提要 使用numpy.random.choice()的时候&#xff0c;通过参数p&#xff08;一个列表&#xff09;来指定所给选择元素的选择概率。但参数p&#xff08;选择概率&#xff09;要保证和为1&#xff0c;这时我又想随机生成选择概率&#xff0c;所以现在的问题就是怎么将1拆分成多…

python随机生成一个数字_如何实现python随机生成数字?

今天小编就生成随机数,整理了多个方式,方便大家在项目时,根据自己的需求,直接拿来套用即可,以下内容相当详细,具体来看看吧~ 说明:python中生成随机数主要用到random模块,方法主要包括:randint、uniform、random、sample、choice等几种常用方法; 环境:Mac OS 10.1…

python随机生成三位数字_python3 随机生成数字

原博文 2019-11-25 10:07 − random模块 random.randint(1,10)--随机生成0-10之间的随机整数 random.uniform(1,10)--随机生成0-10之间的实数 random.randrange(9,100,10)--从9-100之间随机选取一个实数,差为10,也就是说从9,19,29,39,49... 0 3530 相关推荐 2019-12-0…

C#生成含数字字母的随机字符串

C#生成含数字字母的随机字符串 要求生成的字符串是随机的&#xff0c;也就是字母和数字都需要随机&#xff0c;既可能只包含数字&#xff0c;也可能只包含字母&#xff0c;也可能两者都有。 实现方式如下: 首先定义一个包含所有字母和数字的字符串和一个空串&#xff0c;随后…

css 随机 数,纯CSS实现随机效果

最近在Codepen上看到了Adir写的随机翻牌和找蛋蛋(可以想象是砸金蛋)效果&#xff0c;让我再次刷新了对CSS的认知。看到这两个效果之后我才知道&#xff0c;在CSS中除了可以实现 来自其他语言的随机性 众所周知&#xff0c;CSS是一种声明式的标记语言。在很多同学的认知中&#…

舒尔特表-5*5表格1-25个数字随机生成且不重复

大家好&#xff1a;最近在玩快速记忆&#xff0c;看到舒尔特表&#xff0c;整理出一版来。v1.0版本。 舒尔特表&#xff1a;5*5表格 1-25个数字&#xff0c;随机生成且不重复。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:/…

计算机随机数字excel,excel怎么生成随机数字 excel随机数字区间怎么设定

excel是我们日常生活中处理表格数据必备的工具&#xff0c;当我们知道了一定范围内的数值&#xff0c;并且不用精准的数值时&#xff0c;我们完全可以设置excel随机生成数字即可&#xff0c;怎么设置?很简单&#xff0c;下面小编为大家带来excel生成随机数字的详细教程&#x…

随机生成4个数字php,PHP随机生成4位数字的方法

//方法1 $code .mt_rand(1000,9999).; echo $code; echo ; //方法2 $code .mt_rand(1000,9999).; echo $code; echo ; //方法3 $code ; $code..mt_rand(0,9).; $code..mt_rand(0,9).; $code..mt_rand(0,9).; $code..mt_rand(0,9).; echo $code; echo ; //方法4 $code ; $r…

java生成1到10的随机数_用java生成一个1到10十个数字随机排列的数组

效果如图&#xff1a; 代码如下public class ArrayListToAry { public static void main(String[] args) { // 数组 int[] ary new int[10]; // 集合 ,临时集合temp存放1~10个数字 ArrayList temp new ArrayList(); //list集合存放需要的数字 ArrayList list new ArrayList(…

你知道如何生成随机数吗?(超详细附图)

目录 &#x1f609;前言 &#x1f378;如何用C语言实现随机数 &#x1f379;随机数原理 &#x1f379;rand函数&#xff08;生成随机数&#xff09; &#x1f379;srand&#xff08;避免每次运行程序产生的随机数都相同&#xff09; &#x1f379;时间戳 &#x1f964;t…

如何批量生成个位随机数字

众所周知&#xff0c;条码软件可以批量打印条码二维码以及各种各样的产品标签&#xff0c;功能比较齐全&#xff0c;在输入数据时有各种类型&#xff0c;比如手动输入、计数器生成、数据库字段、日期时间、序列生成、流水号等等。今天小编给大家介绍如何随机生成个位数字。 打开…

使用cmd查看端口号

打开cmd命令窗口&#xff1b;输入 netstat -nao|findstr "端口号" &#xff1b;在本地地址中查看端口号&#xff0c;并记住该进程的PID&#xff1a;在运行中输入taskmgr打开任务管理器&#xff0c;在名称一处右击&#xff0c;选中PID&#xff1b;查看第三步的PID所对…

【cmd命令】查看端口占用情况

1、昨晚安装BIS 6遇到一个问题&#xff0c;本地10000端口被占用&#xff0c;安装进行不下去。 2、通过netstat -ano&#xff08;-a 显示所有socket&#xff0c;包括正在监听的&#xff1b;-n 以网络IP地址代替名称&#xff0c;显示出网络连接&#xff1b;o查看进程pid&#xff…

windows cmd关闭端口命令

netstat -ano|findstr 8906taskkill /pid 23440 /f

cmd解决端口被占用

文章目录 一、winr打开cmd窗口二、查找被占用端口的pid号&#xff0c;例如8080端口三、通过命令杀掉当前pid进程总结 一、winr打开cmd窗口 二、查找被占用端口的pid号&#xff0c;例如8080端口 输入命令&#xff1a;netstat -aon|findstr "8080" 如果有如下输出&…

cmd命令查看端口,并强制关闭该端口号

1.查看端口&#xff08;删除8080是指查看所有端口&#xff09; netstat -aon|findstr 8080 2.强制关闭端口号 taskkill /pid 3784 /f 例如&#xff1a;效果如下图