自旋

Linux内核同步方法

百般思念 提交于 2019-11-27 00:43:34
1、原子操作,是其它同步方法的基础。 2、自旋锁,线程试图获取一个已经被别人持有的自旋锁,当前线程处于忙等待,占用cpu资源。 3、读写自旋锁,根据通用性和针对性的特点,普通自旋锁在特定场景下的表现会退化。因此,提供了读写自旋锁,读锁可以加读锁,不能加写锁,写锁不能加任何锁。 4、需要注意的几项:   普通自旋锁是不能递归的。读锁可以递归,写锁也不能递归。   表面上锁的是代码,实际上锁的是共享数据。   使用读写锁的时候,需要注意,读锁可以加读锁,多个线程都占用读锁,必须所有的线程都释放,才能加上写锁,这往往会导致写锁长时间处于饥饿状态。 5、自旋锁存在的问题,线程试图获取一个已经被别人持有的自旋锁,当前线程处于忙等待,占用cpu资源。怎么解决这个问题?   使用信号量,信号量是一种睡眠锁。一个任务试图获取被别人占有的信号量,信号量会将其推进一个等待队列,让其睡眠,当请求的信号量被释放,处于等待队列的任务被唤醒,并获得信号量。 6、需要注意的是,信号量是一种睡眠锁,但它本身也会带有开销,上下文切换,被阻塞的线程要换出换入,也即是说让其睡眠并唤醒它,花费一定的开销。如果每个线程锁的时间很短,一般使用自旋锁,忙等待的时间也很短。如果锁的时间长,使用信号量。 7、相比自旋锁,信号量还有更广泛的用处,使用PV操作不仅能保护共享资源,还能够控制同时访问的数量,还能够控制访问顺序。对于锁

AQS源码分析--jdk1.8

蓝咒 提交于 2019-11-26 17:18:43
# **JDK1.8** [ArrayList源码分析--jdk1.8](https://blog.51cto.com/hackerxian/2426030) [LinkedList源码分析--jdk1.8](https://blog.51cto.com/hackerxian/2426840) [HashMap源码分析--jdk1.8](https://blog.51cto.com/hackerxian/2427207) [AQS源码分析--jdk1.8](https://blog.51cto.com/hackerxian/2427864) # **AbstractQueuedSynchronizer概述** >   1. AQS是一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架。 >   2. AQS提供了双向链表。 >   3. AQS分为共享模式和独占模式。 >   4.AQS基于volatile内存可见性和CAS原子性操作实现线程间通信操作。 # **AbstractQueuedSynchronizer数据结构** >   数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据结构是我们分析源码的必经之路。 >   AQS的数据结构如下:双向链表 >   ![](https://s1.51cto.com/images/blog

线程中锁的分类

时光怂恿深爱的人放手 提交于 2019-11-26 13:02:31
原文: https://www.jianshu.com/p/46bd98ea9845 公平锁与非公平锁: https://www.cnblogs.com/DDiamondd/p/11316393.html 自旋锁与阻塞锁: 自旋锁: 是指当线程获取锁失败的时候,去执行一个无意义的循环,循环结束后再重新去竞争锁,如果竞争不到则继续循环。整个过程中线程一直处于运行(running)状态。 阻塞锁: 和自旋锁相对,指当线程获取锁失败时,线程进入阻塞(blocking)状态,当获取相应的信号时(唤醒,时间),进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。 自旋锁的出现原因: 线程的阻塞和唤醒需要CPU从用户态转为核心态,频繁的阻塞和唤醒对CPU来说是一件负担很重的工作。而且,很多对象锁的锁定状态只会持续很短的一段时间,例如整数的自加操作,在很短的时间内阻塞并唤醒线程显然不值得,为此引入了自旋锁。 适用情况: 自旋等待不能代替阻塞。自旋等待本身虽然,但它是要占用处理器时间的,因此,如果锁被占用的时间很短,自旋当代的效果就会非常好,反之,如果锁被占用的时间很长,那么自旋的线程只会白白浪费处理器资源。 可重入锁和不可重入锁: 可重入锁: 指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。即获取锁的粒度是线程而不是调用。 不可重入锁:

SpinWait 第二篇

本小妞迷上赌 提交于 2019-11-26 12:39:15
SpinWait 提供了两个方法和两个只读属性。 方法: SpinWait.Reset() : 重置自旋计数器,将计数器置 0。效果就好像没调用过SpinOnce一样。 SpinWait.Once() : 执行一次自旋。当SpinWait自旋达到一定次数后,如果有必要当前线程会让出底层的时间片并触发上下文切换。 属性: SpinWait.Count:方法执行单次自旋的次数。 SpinWait.NextSpinWillYield:一个bool值,表示下一次通过SpinOnce方法自旋是否会让出底层线程的时间片并发生上下文切换。 --------------------- 版权声明:本文为CSDN博主「zy__」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wangzhiyu1980/article/details/45814853 来源: https://www.cnblogs.com/yy1234/p/11320403.html