实例讲解Java 自旋锁

2025-05-29 0 28

  一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下;

  所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法);

  我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试;成功的话,就可以到最后的return语句;

  由此我们可以大概知道如果自旋的线程过多,那么CPU的资源就会被大量消耗!!!

实例讲解Java 自旋锁

  顺便提一个东西叫做原子引用,官方提供了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();

}

}

实例讲解Java 自旋锁

  上面的就是一个自旋锁的栗子,执行结果中首先是执行A线程的myLock方法,获取锁成功,之后的B线程虽然也会执行mylock方法,但是会在while循环中一直阻塞,直到线程A调用了myUnlock方法释放锁,最后两行才会打印出来;

以上就是实例讲解Java 自旋锁的详细内容,更多关于Java 自旋锁的资料请关注快网idc其它相关文章!

原文链接:https://www.cnblogs.com/wyq1995/p/12539853.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 实例讲解Java 自旋锁 https://www.kuaiidc.com/117243.html

相关文章

发表评论
暂无评论