a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 159|回复: 2

[程序员] 计算机软件考试程序员:lockfree算法

[复制链接]
发表于 2012-8-2 08:51:15 | 显示全部楼层 |阅读模式
lockfree的本质是乐观锁。也就是说,它假设多数情况下,别人不会改变。一个通用的lockfree算法可描述如下:    lockfree_modify(DataT* data)
5 x8 P9 o; s1 ?    {/ T  e: P/ N. U& [0 e
    for (;;); y! z2 g  u$ |5 P# ?2 i
    {3 g5 ^6 H- j: i9 R) L$ ^+ m% G0 P
    Save old state of data to a local variable;; a9 h' A2 \; _7 w& {/ G
    do modify;. N4 T. t- ]& E3 f2 E; m
    lock {0 R+ ^; Z: A! f4 G2 d) s6 F
    if (current state == old state)
% C5 v2 N" R! D2 \( O    commit modify & return;9 a1 B7 D' l4 v/ l% S5 n/ ]
    }
/ j( x5 e/ O* \8 _# b    }
8 L- }9 R6 v2 C3 e6 \    }
4 }  E; ~  ]( L8 a, A    可以看出,lockfree也是锁,只是将锁限制在一个最小的范围内(通常是一个原子操作)。由于仍然有锁,lockfree在多核下并不会比普通的锁高明多少,它也不能随cpu个数增加而获得呈线性scale的性能提升。
1 _5 S+ v2 I# v, a0 `  q    不过,lockfree有个最大的好处,就是不可能有死锁。因为对上面算法分析你可以知道,在某个线程modify失败,总意味着有另一个人成功了,整个程序总在一步步前进,而不是出现相互等待而产生饥饿的状况。
1 [3 A: O0 j, h1 ^  y. j/ `    我们以stack为例,展示下lockfree的stack是怎样的:
8 E; o  m! L9 o# v8 s+ Q    class stack
, |" x. M) @' t( W    {
; p1 T& p9 z) Q1 h* A8 }    public:7 I) E; l; b- ?! W2 e" t( `
    struct Node
- N, x% w5 O+ J  r" p  ^+ R  ~    {# O7 U. e# t. `) U) M2 n) W
    Node* prev;
+ l; v6 I9 `+ }7 y    };
$ |- a7 X% j  |7 ]    private:
! B9 P) h* c  s" [    Node* m_head;  L, ?- u' o# J- ^& ?* V$ V
    public:+ ~7 l' }$ h$ W  g$ \8 x! E
    stack()# }0 G" {8 K, D0 n4 n
    : m_head(NULL)
回复

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:16 | 显示全部楼层

计算机软件考试程序员:lockfree算法

{, Z9 o3 M; d4 @) t
    }
; g3 B8 V. E3 N- L- y2 v  a7 _3 J    void push(Node* val)+ r0 W8 A" G+ s3 l" n$ }- u( U
    {
1 R5 ~+ p# Z2 P/ A    for (;;)2 N. A% m% a9 I0 l! J& m. x5 m2 u
    {# v! e; f, N' ]; s
    Node* head = m_head;
* V- q" N, I% ?$ p) P' C    val->prev = head;
. j6 X" W! t3 R5 ?    if (InterlockedCompareExchangePointer((PVOID*)&m_head, val, head) == head)
1 R5 o* m) q, y    return;2 r4 g0 c; M6 j4 e
    }
( A. I, g$ \2 x2 ~    }/ G" u3 A3 x7 T5 s  k
    Node* pop()8 \7 i; ^# w/ l( [! H
    {
" d# ]( z$ m+ S* d. S+ ?* O3 f    for (;;): ]) \# T; v, a( O
    {5 s' j" x  y: ?2 v7 J' w
    Node* head = m_head;
+ X' c  g# a+ y1 H1 m/ `    if (head == NULL)3 Z' z) w6 K0 V, v( {- `
    return NULL;$ t& p# F4 w; z' e
    if (InterlockedCompareExchangePointer((PVOID*)&m_head, head->prev, head) == head)
5 N, C4 G. W6 O# Y9 `4 W1 y3 i/ x    return head;
; f- s: {0 [8 G7 O6 h, F! P    }/ e1 i9 s3 o- U9 r' Y2 Q" |/ ]
    }, w! U  g* Y- Y
    };- N  f& h+ A# m6 }
    嗯,看起来挺不错,代码还算优雅。。。不过遗憾的是,严谨的说其实上面的lockfree算法是有问题的。问题在哪里?在pop算法上。我们看lock范围内的语义:
+ H) F1 u6 w& S* D+ L& U9 |    if (InterlockedCompareExchangePointer((PVOID*)&m_head, head->prev, head) == head)4 Y( U1 `: U1 g- u& {, D
    return head;$ b2 ^( ]& Q2 D: J; |/ ~8 j5 t% B
    这句话用伪代码描述是:/ n4 f. Z3 R; J1 ?. e
    lock {3 D, d1 u. }& U" A8 a( \. q+ X
    if (m_head == head) {
7 t8 S6 ~* I; o& r    m_head = head->prev;5 F% {( |" K/ m, v+ E
    return head;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:17 | 显示全部楼层

计算机软件考试程序员:lockfree算法

}
! r# z3 Y2 H2 j: m    }' p# q; c3 @2 L- {
    问题在于,m_head指针的值没有发生变化,和整个stack没有发生变化,这两者等价吗? % Y, a7 Z: O$ c: D' n# r
    不等价。完全可以发生一种情况就是,另一个线程执行了这样一段代码:$ W1 j; U, L/ _0 Y( g- ]1 v  a
    v1 = pop(); // v1是m_head
7 V4 H' g+ C0 C/ v* D1 }    v2 = pop();9 d8 M0 ?, \7 r( [; G+ t- x. G" ?, O
    push(v1);3 s6 P# E9 v, i
    此时,m_head没有变化,但是m_head->prev不再是v2,而是v2->prev了。. W% i; \; @* D/ h+ l0 W
    那么怎么办?在说解决方案前,我们先再聊下上例中的stack::push。既然stack::pop有问题,那么stack::push呢?我们说,push算法的并没有什么问题。尽管同样的,m_head指针的值没有发生变化,并不意味着整个stack没有发生变化。
4 q& `: J5 u8 y" G* o* k& ^但是对于push来说,它只关心m_head,而不关心其他东西,所以stack是否发生变化对其并无影响。
. e7 j! ?$ N/ u' B! x* g# a5 _+ R    那么,应该如何解决pop算法遇到的问题?一个比较通用的方法,就是版本号。lockfree算法中,有一个术语叫tagged_ptr,其实本质上就是一个打了版本号的pointer:
& g6 P3 m1 M- ]4 n4 v9 C1 h9 O    struct tagged_ptr
2 j2 @* u2 T) @* ^2 h2 ?4 y    {
& v! L) X1 F* z7 A) g: i; Y) z    void* p;
. ]. P( ~; V* d+ D% G: H    size_t tag;) d3 H) I, F9 ?6 D8 \7 M
    };
" h7 Y9 s' E* Y2 R1 I    每次要对p进行修改,都++tag。这样,判断是不是modify,只需要判断tag是否变化即可。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-9-21 09:15 , Processed in 0.204386 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表