日期:2014-05-16 浏览次数:20711 次
原子操作时同步方法的基石。原子操作可以保证指令以原子的方式执行,执行过程中不被打断。原子操作绝对不可能并发地访问同一个变量,这样操作也就绝不可能引起竞争。
我个人觉得这个方式不是很好,毕竟有些操作不能提供原子操作,有些必须在很多步骤中的操作。
临界区可能跨越多个函数,对于这种情况原子操作时无能为力的,这就需要更为复杂的同步方法--锁来提供保护
linux中最常见的就是自旋锁,自旋锁最多只能被一个可执行线程持有。在任意时刻,自旋锁都可以防止多于一个的执行线程同时进入临界区。同一个锁可以用在多个位置。结合上一篇文章介绍的锁的例子,自旋锁相当于坐在门外等待同伴从里面出来,并把钥匙交给你,如果你到了门口,发现里面没有人,就可以抓到钥匙进入房间。发现有人,就必须在门外等待钥匙,不断检查房间是否为空。
一个被争用的自旋锁使得请求他的线程在等待重新可用时自旋,这种行为是自旋锁的要点。
自旋锁是不可递归的。
自旋锁可以使用在中断处理程序中(此处不能使用信号量,以为它们会导致睡眠)。在中断处理程序中使用自旋锁时,一定要在获取锁之前,首先禁止本地中断。
在于下半部配合使用时,必须小心地使用锁机制。函数spin_lock_bh()用于获取指定锁,同时它会禁止所有下半部的执行。由于下半部可以抢占进程上下文中的代码,所以当下半部和进程上下文共享数据时,必须对进程上下文中的共享数据进行保护,所以需要加锁的同时还要禁止下半部执行。同样,由于中断处理程序可以抢占下半部,所以如果中断处理程序和下半部共享数据,那么就必须在获取恰当的锁的同时还要禁止中断。
linux中的信号量是一种睡眠锁,如果一个任务试图会的一个不可用的信号量是,信号量会将其推进一个等待队列,然后让其睡眠。
再次回到门和钥匙的问题。当某个人到了门前,他抓起钥匙,然后进入房间。最大的差异在于当另一个人到了门前,当无法得到钥匙时会发生什么情况。在这种情况下,这家伙不是在徘徊等待,而是把自己的名字写在一个列表中,然后就去打盹了。当里面的人离开是,就在门口查看一下列表。如果列表上有名字,他就对第一个名字仔细检查,叫醒他,让他进入房间。
当提到信号时就有计数信号量和二值信号量区别。