为啥spinlock里面不能sleep

1. splin_lock在linux下面的实现,会禁止内核抢占,
    代码如下:
          static inline void __spin_lock(spinlock_t *lock)
{
     preempt_disable();
     spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
}

2.  这里禁止抢占,是指禁止内核抢占。
     所谓内核抢占是指:
       内核进程在中断处理返回,
       schedule调度。
       等。。。 (这个还要具体分析)
3.  在splin_lock里面不能使用sleep操作。
      假设任务A,拿到splin_lock之后,调用sleep了。 而sleep之后,A让出CPU,这个时候会发生任务调度。 
      任务B进来了,正好B也要获取splin_lock,那B一直在忙等状态,当然这个时候,B又禁止抢占的,那么B就不会让出CPU了。
      B不让出CPU,A不能执行,不能释放spin_lock,
      此时死锁发生。
      过程如下:(来自于: http://sabolasi.iteye.com/blog/1246067 )

导致死锁的过程:[1]为进程1,[2]为进程2,

[1] 关抢占

[1] 获得锁

[1] 睡眠调度 ...... 尽管已经关闭了抢占,[1]依然可以通过主动调用schedule(), schedule_timeout()等主动让出CPU,调度其它进程。

[2] 关抢占 ...... [1]已经关闭抢占,所以这里相当于nop操作

[2] 获得锁失败 ...... [1]已经获得了锁,并且还没有释放

[2] 反复尝试获得锁 ...... 由于关闭了抢占,已经没人能够终止这个反复尝试的操作了,所以这里出现了死锁

Linux中的spinlock是一种自旋锁机制,用于保护对共享资源的访问,以防止同时访问导致的数据竞争问题。spinlock使用了一种称为自旋的技术,即当一个线程需要获取锁时,它会一直等待,直到锁被释放。这种等待是循环的,即线程会不断地检查锁的状态,直到锁被释放为止。 spinlock相比于传统的互斥量(mutex)和信号量(semaphore)等锁机制,具有更高的性能和灵活性。spinlock不需要使用内核调度器,因此不会产生额外的上下文切换开销。此外,spinlock可以用于任何需要保护的临界区代码,而不仅仅是用于进程之间的同步。 使用spinlock时,需要将其初始化为0,以便其他线程可以安全地访问共享资源。当一个线程需要获取锁时,它可以使用spin_lock函数来锁定spinlock。如果锁已经被其他线程占用,该线程将进入自旋状态,不断检查锁的状态。当该线程获取到锁时,它可以将共享资源置于临界区并执行相关操作。在操作完成后,该线程可以使用spin_unlock函数释放锁。 spinlock机制适用于一些简单的同步场景,例如在并发访问共享资源时保护临界区代码。然而,对于一些复杂的同步需求,可能需要使用更高级的同步机制,如读写锁(rwlock)或条件变量(condition variable)。 总之,spinlock是一种轻量级的自旋锁机制,适用于简单的同步场景,具有较高的性能和灵活性。它适用于任何需要保护的临界区代码,而不仅仅是用于进程之间的同步。在使用spinlock时,需要注意避免死锁和过度自旋等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值