一、自旋锁的概念

首先是一种锁,与互斥锁相似,基本作用是用于线程(进程)之间的同步。与普通锁不同的是,一个线程A在获得普通锁后,如果再有线程B试图获取锁,那么这个线程B将会挂起(阻塞);试想下,如果两个线程资源竞争不是特别激烈,而处理器阻塞一个线程引起的线程上下文的切换的代价高于等待资源的代价的时候(锁的已保持者保持锁时间比较短),那么线程B可以不放弃CPU时间片,而是在“原地”忙等,直到锁的持有者释放了该锁,这就是自旋锁的原理,可见自旋锁是一种非阻塞锁。

二、自旋锁可能引起的问题:

1.过多占据CPU时间:如果锁的当前持有者长时间不释放该锁,那么等待者将长时间的占据cpu时间片,导致CPU资源的浪费,因此可以设定一个时间,当锁持有者超过这个时间不释放锁时,等待者会放弃CPU时间片阻塞;

2.死锁问题:试想一下,有一个线程连续两次试图获得自旋锁(比如在递归程序中),第一次这个线程获得了该锁,当第二次试图加锁的时候,检测到锁已被占用(其实是被自己占用),那么这时,线程会一直等待自己释放该锁,而不能继续执行,这样就引起了死锁。因此递归程序使用自旋锁应该遵循以下原则:递归程序决不能在持有自旋锁时调用它自己,也决不能在递归调用时试图获得相同的自旋锁。

三、JAVA中一种自旋锁的实现:

<span style="font-size:14px;">import java.util.concurrent.atomic.AtomicReference;
class SpinLock {
//java中原子(CAS)操作
AtomicReference<Thread> owner = new AtomicReference<Thread>();//持有自旋锁的线程对象
private int count;
public void lock() {
Thread cur = Thread.currentThread();
//lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。当有第二个线程调用lock操作时由于owner值不为空,导致循环 //一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。
while (!owner.compareAndSet(null, cur)){
}
}
public void unLock() {
Thread cur = Thread.currentThread();
owner.compareAndSet(cur, null);
}
}
}
public class Test implements Runnable {
static int sum;
private SpinLock lock; public Test(SpinLock lock) {
this.lock = lock;
}
public static void main(String[] args) throws InterruptedException {
SpinLock lock = new SpinLock();
for (int i = 0; i < 100; i++) {
Test test = new Test(lock);
Thread t = new Thread(test);
t.start();
} Thread.currentThread().sleep(1000);
System.out.println(sum);
} @Override
public void run() {
this.lock.lock();
sum++;
this.lock.unLock();
}
}</span>

四、java CAS

CAS是一种系统原语,是Compare And Set的缩写。

自旋锁原理及java自旋锁的更多相关文章

  1. synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

    本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...

  2. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  3. synchronized底层实现原理&CAS操作&偏向锁、轻量级锁,重量级锁、自旋锁、自适应自旋锁、锁消除、锁粗化

    进入时:monitorenter 每个对象有一个监视器锁(monitor).当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:1 ...

  4. AQS学习(一)自旋锁原理介绍(为什么AQS底层使用自旋锁队列?)

    1.什么是自旋锁? 自旋锁作为锁的一种,和互斥锁一样也是为了在并发环境下保护共享资源的一种锁机制.在任意时刻,只有一个执行单元能够获得锁. 互斥锁通常利用操作系统提供的线程阻塞/唤醒机制实现,在争用锁 ...

  5. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...

  6. 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  7. 写文章 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  8. Java中的常见锁(公平和非公平锁、可重入锁和不可重入锁、自旋锁、独占锁和共享锁)

    公平和非公平锁 公平锁:是指多个线程按照申请的顺序来获取值.在并发环境中,每一个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个就占有锁,否者就会加入到等待队列中,以 ...

  9. 深入介绍Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

随机推荐

  1. Session超时问题(AOP 过滤器)

    public class TimeoutAttribute : ActionFilterAttribute { public override void OnActionExecuting(Actio ...

  2. shiro 解决 跨域(仅端口不同) 登陆 问题

    1. 登陆成功设置cookie (服务端 通过 json返回 token) //设置cookie document.cookie = "JSESSIONID="+data.data ...

  3. error C2065:!错误:未定义标识符“pBuf);”

    error C2065: “pBuf):”: 未声明的标识符 错误原因:第二个括号)使用的是中文符号!还有最后那个分号! 改回来就好了~ 原错误: 修正后错误消失:

  4. [转]在ubuntu下安装sublime text

    1添加Sublime-text-3软件包的软件源sudo add-apt-repository ppa:webupd8team/sublime-text-3 2使用以下命令更新系统软件源sudo ap ...

  5. 如何查看nginx的版本及配置选项?nginx都配置了哪些的模块?

    需求描述: 新接手别人的nginx,想要查看当前都配置了哪些模块 操作过程: 1.通过nginx -V选项查看nginx的配置选项 [root@hadoop3 sbin]# ./nginx -V ng ...

  6. mac 开发环境安装使用 记录

    常用命令 1 查找文件位置: $locate php-fpm 软件变动的话更新locate本地库,可能比较耗时. $sudo /usr/libexec/locate.updatedb 2 查找运行文件 ...

  7. wm_concat函数 用法

    首先让我们来看看这个神奇的函数wm_concat(列名),该函数可以把列值以","号分隔起来,并显示成一行,接下来上例子,看看这个神奇的函数如何应用 准备测试数据 SQL>  ...

  8. 关于直播学习笔记-004-nginx-rtmp、srs、vlc、obs

    1.采集端:OBS RTMP推流地址:rtmp://192.168.198.21:1935/live 流密钥:livestream(任意-但播放地址与此一致) 2.播放端:nginx-rtmp-win ...

  9. 通过ArcGIS Desktop数据发布ArcGIS Server

    1.双击GIS Servers--->Add ArcGIS Server 2.选择Publish GIS Services 3.输入Server URL:http://localhost:608 ...

  10. exp/imp与expdp/impdp区别

    在平常备库和数据库迁移的时候,当遇到大的数据库的时候在用exp的时候往往是需要好几个小时,耗费大量时间.oracle10g以后可以用expdp来导出数据库花费的时间要远小于exp花费的时间,而且文件也 ...