Linux 自旋锁
来源:互联网 发布:淘宝充值米币靠谱吗 编辑:程序博客网 时间:2024/05/29 13:07
1.什么是自旋锁
自旋锁顾名思义首先是一把锁,另外使用这把锁的线程需要反复自我循环(loop)检测这把锁是否可用。
注意与信号量区别,信号量也是一把锁,但是使用这把锁的线程检测锁不可用时,选择去睡眠,而不是自我循环。
自旋锁与信号量相同点是两者都是锁,都具备锁定特性,实现临界区代码块的同步与互斥访问。
2.自旋锁实现(摘自http://en.wikipedia.org/wiki/Spinlock)
不同体系结构不同,所以实现自旋锁方式不一样,下面是Intel 80386简单实现,可以进行进一步优化,详细代码参照Linux内核。 功能反复测试
; Intel syntax
lock: ; The lock variable. 1 = locked, 0 = unlocked.
dd 0
spin_lock:
mov eax, 1 ; Set the EAX register to 1.
xchg eax, [lock] ; Atomically swap the EAX register with
; the lock variable.
; This will always store 1 to the lock, leaving
; previous value in the EAX register.
test eax, eax ; Test EAX with itself. Among other things, this will
; set the processor's Zero Flag if EAX is 0.
; If EAX is 0, then the lock was unlocked and
; we just locked it.
; Otherwise, EAX is 1 and we didn't acquire the lock.
jnz spin_lock ; Jump back to the MOV instruction if the Zero Flag is
; not set; the lock was previously locked, and so
; we need to spin until it becomes unlocked.
ret ; The lock has been acquired, return to the calling
; function.
spin_unlock:
mov eax, 0 ; Set the EAX register to 0.
xchg eax, [lock] ; Atomically swap the EAX register with
; the lock variable.
ret ; The lock has been released
3.自旋锁使用注意事项
由于自旋锁最主要特性是不断反复循环测试,注定下列场景需注意:
1.临界区代码不要存在睡眠情况(主要因为发生睡眠不可预知睡眠多长时间,另外长时间睡眠,导致即将进入临界区其他线程,长时间得不到自旋锁,无休止自旋,从而导致死锁),所以临界区调用导致睡眠函数,不能选择自旋锁。
2.保证进入临界区的线程,不发生内核抢占。(这一点不必担心,持有自旋锁情况,Linux内核不进行抢占)
3.临界区代码,执行时间不能太长。(因为其他线程,如果要进入话,导致自旋,过多消耗CPU资源)
4.选择自旋锁时,也要注意中断情况(上半部分中断(硬件中断)和下半部分中断(软中断),中断会抢占即中断到来时,打断目前临界区代码执行,转往执行中断代码),当中断要进入自旋锁保护临界区代码时,将导致线程与中断发生死锁可能。
4Linux内核中提供自旋锁函数
1)自旋锁头文件
<linux/spinlock.h>
2)自旋锁数据类型
spinlock_t
3)自旋锁变量静态初始化
spinlock_t lock = SPIN_LOCK_UNLOCKED;
4)自旋锁变量动态初始化
spinlock_t lock
spin_lock_init(&lock);
5)锁定函数
void spin_lock(spinlock_t *lock);
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
void spin_lock_irq(spinlock_t *lock); 禁止(屏蔽硬件中断)自旋锁,针对场合4情况
void spin_lock_bh(spinlock_t *lock);禁止(屏蔽下半部分中断)自旋锁,针对场合4情况
6)解锁函数
void spin_unlock(spinlock_t *lock);
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
void spin_unlock_irq(spinlock_t *lock);
void spin_unlock_bh(spinlock_t *lock);
自旋锁顾名思义首先是一把锁,另外使用这把锁的线程需要反复自我循环(loop)检测这把锁是否可用。
注意与信号量区别,信号量也是一把锁,但是使用这把锁的线程检测锁不可用时,选择去睡眠,而不是自我循环。
自旋锁与信号量相同点是两者都是锁,都具备锁定特性,实现临界区代码块的同步与互斥访问。
2.自旋锁实现(摘自http://en.wikipedia.org/wiki/Spinlock)
不同体系结构不同,所以实现自旋锁方式不一样,下面是Intel 80386简单实现,可以进行进一步优化,详细代码参照Linux内核。 功能反复测试
; Intel syntax
lock: ; The lock variable. 1 = locked, 0 = unlocked.
dd 0
spin_lock:
mov eax, 1 ; Set the EAX register to 1.
xchg eax, [lock] ; Atomically swap the EAX register with
; the lock variable.
; This will always store 1 to the lock, leaving
; previous value in the EAX register.
test eax, eax ; Test EAX with itself. Among other things, this will
; set the processor's Zero Flag if EAX is 0.
; If EAX is 0, then the lock was unlocked and
; we just locked it.
; Otherwise, EAX is 1 and we didn't acquire the lock.
jnz spin_lock ; Jump back to the MOV instruction if the Zero Flag is
; not set; the lock was previously locked, and so
; we need to spin until it becomes unlocked.
ret ; The lock has been acquired, return to the calling
; function.
spin_unlock:
mov eax, 0 ; Set the EAX register to 0.
xchg eax, [lock] ; Atomically swap the EAX register with
; the lock variable.
ret ; The lock has been released
3.自旋锁使用注意事项
由于自旋锁最主要特性是不断反复循环测试,注定下列场景需注意:
1.临界区代码不要存在睡眠情况(主要因为发生睡眠不可预知睡眠多长时间,另外长时间睡眠,导致即将进入临界区其他线程,长时间得不到自旋锁,无休止自旋,从而导致死锁),所以临界区调用导致睡眠函数,不能选择自旋锁。
2.保证进入临界区的线程,不发生内核抢占。(这一点不必担心,持有自旋锁情况,Linux内核不进行抢占)
3.临界区代码,执行时间不能太长。(因为其他线程,如果要进入话,导致自旋,过多消耗CPU资源)
4.选择自旋锁时,也要注意中断情况(上半部分中断(硬件中断)和下半部分中断(软中断),中断会抢占即中断到来时,打断目前临界区代码执行,转往执行中断代码),当中断要进入自旋锁保护临界区代码时,将导致线程与中断发生死锁可能。
4Linux内核中提供自旋锁函数
1)自旋锁头文件
<linux/spinlock.h>
2)自旋锁数据类型
spinlock_t
3)自旋锁变量静态初始化
spinlock_t lock = SPIN_LOCK_UNLOCKED;
4)自旋锁变量动态初始化
spinlock_t lock
spin_lock_init(&lock);
5)锁定函数
void spin_lock(spinlock_t *lock);
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
void spin_lock_irq(spinlock_t *lock); 禁止(屏蔽硬件中断)自旋锁,针对场合4情况
void spin_lock_bh(spinlock_t *lock);禁止(屏蔽下半部分中断)自旋锁,针对场合4情况
6)解锁函数
void spin_unlock(spinlock_t *lock);
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
void spin_unlock_irq(spinlock_t *lock);
void spin_unlock_bh(spinlock_t *lock);
0 0
- LINUX 自旋锁
- 自旋锁 for linux
- linux 自旋锁 spin_lock
- Linux内核自旋锁
- LINUX自旋锁详解
- LINUX自旋锁详解
- LINUX自旋锁详解
- linux的自旋锁
- Linux 自旋锁
- linux自旋锁
- Linux 自旋锁
- linux自旋锁
- Linux自旋锁
- Linux 自旋锁
- Linux 自旋锁
- linux自旋锁理解
- linux自旋锁
- Linux自旋锁
- Cocos2d-x 屏幕适配解决方案
- NodeJS优缺点及适用场景讨论
- smali修改Textview+smali常用语法
- 安卓文件读取
- 深入同步语法
- Linux 自旋锁
- 每日一思
- 减少GC回收
- bitmap两篇文章
- Java IO流学习总结
- Hadoop 2.0 – HA功能中ZKFC对NN状态的控制
- 用女神Nalu的黄金秀发做毛笔––毛笔书法实时模拟技术的终极解决方案
- gSoap心得
- spring mvc与html中处理引用js等静态文件的问题