Java锁-自旋锁
1、什么是自旋锁
自旋锁是为实现保护共享资源而提出一种锁机制,用于多线程同步的一种锁,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。它是一种非阻塞锁,也就是说,如果某线程需要获取锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取锁。
自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,这就是"自旋"。
2、Java是如何实现自旋锁?
手写demo实现自旋锁,
import java.util.concurrent.atomic.AtomicReference; public class SpinLock { private AtomicReference<Thread> cas = new AtomicReference<Thread>(); public void lock() { Thread current = Thread.currentThread(); while (!cas.compareAndSet(null, current)) { // 利用CAS // 什么都不做,自旋 } System.out.println(Thread.currentThread().getName()+"\t get lock"); } public void unlock() { Thread current = Thread.currentThread(); cas.compareAndSet(current, null); System.out.println(Thread.currentThread().getName()+"\t release lock"); } }
并测试代码,线程使用自旋方式获取锁,然后模拟2s的逻辑处理任务,
ExecutorService executorService = Executors.newFixedThreadPool(2); final CountDownLatch countDownLatch = new CountDownLatch(2); final SpinLock spinLock = new SpinLock(); for (int i = 0 ; i < 2 ; i++){ executorService.execute(new Runnable() { @Override public void run() { spinLock.lock(); System.out.println(Thread.currentThread().getName()+"\t开始运行"); ++count; SystemClock.sleep(2000); System.out.println(Thread.currentThread().getName()+"\t结束运行"); spinLock.unlock(); countDownLatch.countDown(); } }); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); }
运行结果:
通过代码可以看出,自旋就是在循环判断条件是否满足,如果锁被占用很长时间的话,自旋的线程等待的时间也会变长,白白浪费掉处理器资源。因此在JDK中,自旋操作默认10次,我们可以通过参数“-XX:PreBlockSpin”来设置,当超过来此参数的值,则会使用传统的线程挂起方式来等待锁释放。
但是自旋锁也是有优点的,自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是active的;不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快。非自旋锁在获取不到锁的时候会进入阻塞状态,从而进入内核态,当获取到锁的时候需要从内核态恢复,需要线程上下文切换,严重影响锁的性能。
3、自适应自旋锁
随着JDK的更新,在1.6的时候,出现了“自适应自旋锁”。所谓的“自适应”意味着对于同一个锁对象,线程的自旋时间是根据上一个持有该锁的线程的自旋时间以及状态来确定的。例如对于A锁对象来说,如果一个线程刚刚通过自旋获得到了锁,并且该线程也在运行中,那么JVM会认为此次自旋操作也是有很大的机会可以拿到锁,因此它会让自旋的时间相对延长。但是如果对于B锁对象自旋操作很少成功的话,JVM甚至可能直接忽略自旋操作。
因此,自适应自旋锁是一个更加智能,对我们的业务性能更加友好的一个锁。
4、JAVA自旋锁应用
Jdk 提供的java.util.concurrent.atomic包里面提供了一组原子类。 基本上就是当前获取锁的线程,执行更新的方法,其他线程自旋等待,比如atomicInteger类中的getAndAdd方法内部实际上使用的就是Unsafe的方法。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
绿色机器人如何帮助环境可持续发展
云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! 绿色机器人可以帮助我们对抗气候变化,并带领我们走向更美好的未来。 我们通常不认为机器人是“环保的”。到目前为止,我们所看到的最接近热爱地球的机器人可能是“Wall-e瓦力”了。但是,由于绿色机器人,利用机器人来实现可持续发展很快就会成为现实。气候变化需要比以往任何时候都更加迫切得到遏制,如今,我们已经开始利用人工智能、区块链和物联网等技术来应对气候变化。而绿色机器人也可以支持我们应对气候变化。各种各样的机器人已经被开发出来,它们能够以各种方式帮助保护环境,从扑灭野火,帮助管理垃圾,到清洁海洋和其他水体等。以下是绿色机器人帮助环境可持续发展的几种方法: 绿色机器人在可持续发展中的应用 由于人类活动,全球气温已上升到近4000年来的最高点。如果我们不迅速采取行动,这将使我们走上自我毁灭的道路。先进技术的出现有助于简化我们的生计努力,并有助于减缓气候变化的影响。绿色机器人可以帮助实现自动化,并以最高的效率完成环保任务,而不会感到疲劳。 1....
- 下一篇
Redis rdb文件内存分析
需要安装Python2.7:yum -y install zlib*wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgztar -zxvf Python-2.7.9.tgzcd Python-2.7.9./configure --prefix=/usr/local/python2.7make && make installln -s /usr/local/python2.7/bin/python2.7 /usr/bin/python2.7wget https://bootstrap.pypa.io/get-pip.pypython2.7 get-pip.pyln -s /usr/local/python2.7/bin/pip2.7 /usr/bin/pip2.7pip2.7 install redispip2.7 install rdbtoolspip2.7 install python-lzf 从rds下载rdb备份文件:这里为a.rdbrdb -c memory a.rdb >memory....
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装