欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

实例讲解Java 自旋锁

程序员文章站 2022-03-27 13:45:14
一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下;  所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什...

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

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

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

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

实例讲解Java 自旋锁

  顺便提一个东西叫做原子引用,官方提供了atomicinteger,atomicboolean等原子类,那么如果我们自己定义的类也需要有原子性怎么办呢?所以官方提供了一个atomicreference类,可以将我们自己定义的类封装一下,就成了我们自己的原子类,例如atomicreference<student> atomicreference = new atomicreference<>();,然后我们对student的实例进行cas各种cas操作;

  栗子:

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 自旋锁的资料请关注其它相关文章!

相关标签: Java 自旋锁