- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章实例讲解Java 自旋锁由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下; 。
所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法); 。
我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试;成功的话,就可以到最后的return语句; 。
由此我们可以大概知道如果自旋的线程过多,那么CPU的资源就会被大量消耗!!! 。
顺便提一个东西叫做原子引用,官方提供了AtomicInteger,AtomicBoolean等原子类,那么如果我们自己定义的类也需要有原子性怎么办呢?所以官方提供了一个AtomicReference类,可以将我们自己定义的类封装一下,就成了我们自己的原子类,例如AtomicReference<Student> atomicReference = new AtomicReference<>();,然后我们对Student的实例进行CAS各种CAS操作; 。
栗子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package
TestMain;
import
lombok.extern.slf4j.Slf4j;
import
java.util.concurrent.TimeUnit;
import
java.util.concurrent.atomic.AtomicReference;
@Slf4j
public
class
TestMain80 {
//一个Thread类的原子引用
AtomicReference<Thread> atomicReference =
new
AtomicReference<>();
//加锁的方法
public
void
myLock() {
Thread currentThread = Thread.currentThread();
log.info(
"myLock--Thread:{}"
, currentThread.getName());
//这个就是自旋锁的核心,利用CAS比较当前原子引用中是否为null,如果是null,就把当前线程A放到里面去,
// 此时线程B再到这里,那么就会CAS失败,一直在while循环中
while
(!atomicReference.compareAndSet(
null
, currentThread)) {
}
}
//解锁的方法
public
void
myUnlock() {
Thread currentThread = Thread.currentThread();
//CAS比较原子引用中是不是线程A,是的话就更新为null,此时在上面while中一直在自旋的线程B就可以跳出来了
atomicReference.compareAndSet(currentThread,
null
);
log.info(
"myUnlock--Thread:{}"
, currentThread.getName());
}
public
static
void
main(String[] args) {
TestMain80 testMain80 =
new
TestMain80();
//线程A,首先加锁,然后等3秒中,然后释放锁
new
Thread(() -> {
testMain80.myLock();
try
{
TimeUnit.SECONDS.sleep(
3
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
testMain80.myUnlock();
},
"A"
).start();
//主线程等1秒,保证A线程先执行
try
{
TimeUnit.SECONDS.sleep(
1
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
//线程B,加锁再释放锁
new
Thread(() -> {
testMain80.myLock();
testMain80.myUnlock();
},
"B"
).start();
}
}
|
上面的就是一个自旋锁的栗子,执行结果中首先是执行A线程的myLock方法,获取锁成功,之后的B线程虽然也会执行mylock方法,但是会在while循环中一直阻塞,直到线程A调用了myUnlock方法释放锁,最后两行才会打印出来; 。
以上就是实例讲解Java 自旋锁的详细内容,更多关于Java 自旋锁的资料请关注我其它相关文章! 。
原文链接:https://www.cnblogs.com/wyq1995/p/12539853.html 。
最后此篇关于实例讲解Java 自旋锁的文章就讲到这里了,如果你想了解更多关于实例讲解Java 自旋锁的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
1、流程控制语句主要有if、ii...else、elseif(有时也可以写成else if)、switch四种。 PHP中语句格式为: if(条件满足) {执行语句} if(条件满足) {执行
目录 DFS初步概念 DFS例题-迷宫游戏 题目描述 输入输出格式 输入输出样例
This question两年前被问到,但它提到的资源要么不是很有帮助(恕我直言),要么链接不再有效。 必须有一些很好的教程才能理解 Phaser .我已经阅读了 javadoc,但我的眼睛呆滞了,因
This question两年前被问到,但它提到的资源要么不是很有帮助(恕我直言),要么链接不再有效。 必须有一些很好的教程才能理解 Phaser .我已经阅读了 javadoc,但我的眼睛呆滞了,因
这个正则出自这个网站 http://www.regexlab.com/zh/regref.htm 正向预搜索:"(?=xxxxx)","(?!xxxxx)"
chr(9)、chr(10)、chr(13)、chr(32)、chr(34) 所有关于 ASCII码的表格:[url]http://www.asciitable.com/[/url] chr(13)
我是一名优秀的程序员,十分优秀!