随笔-156  评论-223  文章-30  trackbacks-0
   自旋锁作为一种并发同步的手段,特别适用于竞争少和锁时间短的情况,在驱动及内核代码中经常被用到,本文讲述一种适合用户态程序的自旋锁,支持Windows和Linux(GCC>=4.1.2)平台,并提供了C语言的接口和实现。

接口
   spin_trylock如果获取成功返回1,否则返回0;spin_is_lock如果已加锁,返回1,否则返回0。
 1typedef struct 
 2{
 3 volatile long  flag_;
 4 volatile long* spin_;
 5}
spin_lock_t;
 6
 7void spin_init(spin_lock_t* lock,long* flag);
 8
 9void spin_lock(spin_lock_t* lock);
10
11int spin_trylock(spin_lock_t* lock);
12
13void spin_unlock(spin_lock_t* lock);
14
15int spin_is_lock(spin_lock_t* lock);

实现
 1#ifdef _MSC_VER
 2#include <windows.h>
 3#elif defined(__GNUC__)
 4#if __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<1)
 5#error GCC version must be greater or equal than 4.1.2
 6#endif
 7#include <sched.h>
 8#else
 9#error Currently only windows and linux os are supported
10#endif
11
12void spin_init(spin_lock_t* lock,long* flag)
13{
14#ifdef _MSC_VER
15    InterlockedExchange((volatile long*)&lock->flag_,0);
16    InterlockedExchange((volatile long*)&lock->spin_,flag?(long)flag:(long)&lock->flag_);
17#elif defined(__GNUC__)
18    __sync_and_and_fetch((long*)&lock->flag_,0);
19    __sync_lock_test_and_set((long*)&lock->spin_,flag?(long)flag:(long)&lock->flag_);
20#endif
21}

22
23void spin_lock(spin_lock_t* lock)
24{
25#ifdef _MSC_VER
26    for (;0!=InterlockedExchange((volatile long*)lock->spin_,1);)
27    {
28        Sleep(1);
29    }

30#elif defined(__GNUC__)
31    for (;0!=__sync_fetch_and_or(lock->spin_,1);)
32    {
33        sched_yield();
34    }

35#endif
36}

37
38int spin_trylock(spin_lock_t* lock)
39{
40#ifdef _MSC_VER
41    return !InterlockedExchange((volatile long*)lock->spin_,1);
42#elif defined(__GNUC__)
43    return !__sync_fetch_and_or(lock->spin_,1);
44#endif
45}

46
47void spin_unlock(spin_lock_t* lock)
48{
49#ifdef _MSC_VER
50    InterlockedExchange((volatile long*)lock->spin_,0);
51#elif defined(__GNUC__)
52    __sync_and_and_fetch(lock->spin_,0);
53#endif
54}

55
56int spin_is_lock(spin_lock_t* lock)
57{
58#ifdef _MSC_VER
59    return InterlockedExchangeAdd((volatile long*)lock->spin_,0);
60#elif defined(__GNUC__)
61    return __sync_add_and_fetch(lock->spin_,0);
62#endif
63}
posted on 2012-06-13 21:02 春秋十二月 阅读(3015) 评论(3)  编辑 收藏 引用 所属分类: C/C++

评论:
# re: 一种简单的跨平台用户态自旋锁 2012-06-13 22:57 | egmkang
lock的时候,可以先去获取一下状态,如果都是lock的,那么就没有必要原子操作.
这样效率会高一点.  回复  更多评论
  
# re: 一种简单的跨平台用户态自旋锁 2012-06-22 01:34 | tb
挺不错的   回复  更多评论
  
# re: 一种简单的跨平台用户态自旋锁 2013-09-25 23:00 | egmkang
spin_lock的实现,其实最好的是先判断一下,然后再去尝试着原子操作;否则如果锁碰撞比较大,会把很多实践浪费在原子操作上,不划算.
另外,把变量声明成volatile貌似是不合适的吧.多线程和volatile没有任何关系.
原子操作完成了,其他CPU里面看到的值就一定是最新的,至少在x86体系上面是这样,如果是其他CPU貌似还要加一个barrier.  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理