C 可快速获取的锁

C 可快速获取的锁,c,C,这是一种在两个或更多线程真正访问关键部分之前不使用OS同步原语的算法。即使在同一个线程的递归“锁”中,在涉及第二个线程之前也没有真正的锁 有两个功能: int qrlgeneric_acquire(qrlgeneric_lock *L, int id); void qrlgeneric_release(qrlgeneric_lock *L, int acquiredquickly); qrlgeneric\u acquire:在线程想要锁定时调用id是线程id qrlgeneric\u

这是一种在两个或更多线程真正访问关键部分之前不使用OS同步原语的算法。即使在同一个线程的递归“锁”中,在涉及第二个线程之前也没有真正的锁

有两个功能:

int qrlgeneric_acquire(qrlgeneric_lock *L, int id);  
void qrlgeneric_release(qrlgeneric_lock *L, int acquiredquickly);
qrlgeneric\u acquire:在线程想要锁定时调用<代码>id是线程id
qrlgeneric\u release:当线程想要解锁时调用

示例:
已锁定的线程1再次调用
qrlgeneric\u acquire
,因此将执行递归锁定。同时,Thread_2调用
qrlgeneric_acquire
,因此会出现争用(两个线程想要锁定,将使用真正的os同步原语)

线程_1将在第
4行达到此条件

04 if (BIASED(id) == status) // SO: this means this thread already has this lock
05 {    
06   L->lockword.h.quicklock = 1;
07   if (BIASED(id) == HIGHWORD(L->lockword.data))
08     return 1;
09   L->lockword.h.quicklock = 0; /* I didn’t get the lock, so be sure */
10   /* not to block the process that did */
11 }
线程2将在第
35行达到此条件<代码>CAS
比较和交换原子操作

34 unsigned short biaslock = L->lockword.h.quicklock;
35 if (CAS(&L->lockword,
36   MAKEDWORD(biaslock, status),
37   MAKEDWORD(biaslock, REVOKED)))
38 {
39   /* I’m the revoker. Set up the default lock. */
40   /* *** INITIALIZE AND ACQUIRE THE DEFAULT LOCK HERE *** */
41   /* Note: this is an uncontended acquire, so it */
42   /* can be done without use of atomics if this is */
43   /* desirable. */
44   L->lockword.h.status = DEFAULT;
45
46   /* Wait until quicklock is free */
47   while (LOWWORD(L->lockword.data))
48   ;
49   return 0; /* And then it’s mine */
50 }
9
行和
47
行上的注释中,您可以看到
9
行上的语句用于支持
47
行上的语句,因此线程2不会永远在那里旋转锁定

问题:从第
9
行和第
47
行上的评论来看,上述两个条件永远不会同时成功,否则线程将在第
47
行上旋转锁,因为第
9
行上的语句将不会执行问题是,我需要帮助理解他们两人都成功是怎么可能永远不会发生的,因为我仍然认为这是可能发生的:

1。线程1:
06 L->lockword.h.quicklock=1
2。线程2:
34无符号短biaslock=L->lockword.h.quicklock
3。线程1:
if(偏置(id)=HIGHWORD(L->lockword.data))

4。线程2:
35 if(CAS(&L->lockword,MAKEDWORD(biaslock,status),MAKEDWORD(biaslock,reversed))

3。此条件将成功,因为线程2尚未更改任何内容。
4。此条件将成功,因为点13不会对其产生影响

结果是我认为它们都可以成功,但这意味着线程2将在
47
行上旋转锁,直到线程1释放锁。我认为这绝对是错误的,不应该发生,所以我可能不理解。有人能帮忙吗

整个算法:

/* statuses for qrl locks */
#define BIASED(id) ((int)(id) << 2)
#define NEUTRAL 1
#define DEFAULT 2
#define REVOKED 3
#define ISBIASED(status) (0 == ((status) & 3))
/* word manipulation (big-endian versions shown here) */
#define MAKEDWORD(low, high) (((unsigned int)(low) << 16) | (high))
#define HIGHWORD(dword) ((unsigned short)dword)
#define LOWWORD(dword) ((unsigned short)(((unsigned int)(dword)) >> 16))

typedef volatile struct tag_qrlgeneric_lock
{
  volatile union
  {
    volatile struct
    {
      volatile short quicklock;
      volatile short status;
    }
    h;
    volatile int data;
  }
 lockword;
/* *** PLUS WHATEVER FIELDS ARE NEEDED FOR THE DEFAULT LOCK *** */
}
qrlgeneric_lock;

int qrlgeneric_acquire(qrlgeneric_lock *L, int id)
{
   int status = L->lockword.h.status;

   /* If the lock’s mine, I can reenter by just setting a flag */
   if (BIASED(id) == status)
   {
     L->lockword.h.quicklock = 1;
     if (BIASED(id) == HIGHWORD(L->lockword.data))
       return 1;
     L->lockword.h.quicklock = 0; /* I didn’t get the lock, so be sure */
   /* not to block the process that did */
   }

   if (DEFAULT != status)
   {
   /* If the lock is unowned, try to claim it */
     if (NEUTRAL == status)
     {
       if (CAS(&L->lockword, /* By definition, if we saw */
           MAKEDWORD(0, NEUTRAL), /* neutral, the lock is unheld */
           MAKEDWORD(1, BIASED(id))))
       {
          return 1;
       }
       /* If I didn’t bias the lock to me, someone else just grabbed
       it. Fall through to the revocation code */
       status = L->lockword.h.status; /* resample */
     }

     /* If someone else owns the lock, revoke them */
     if (ISBIASED(status))
     {
       do
       {
         unsigned short biaslock = L->lockword.h.quicklock;
         if (CAS(&L->lockword,
             MAKEDWORD(biaslock, status),
             MAKEDWORD(biaslock, REVOKED)))
         {
          /* I’m the revoker. Set up the default lock. */
          /* *** INITIALIZE AND ACQUIRE THE DEFAULT LOCK HERE *** */
          /* Note: this is an uncontended acquire, so it */
          /* can be done without use of atomics if this is */
          /* desirable. */
           L->lockword.h.status = DEFAULT;

           /* Wait until quicklock is free */
           while (LOWWORD(L->lockword.data))
           ;
           return 0; /* And then it’s mine */
          }

          /* The CAS could have failed and we got here for either of
          two reasons. First, another process could have done the
          revoking; in this case we need to fall through to the
          default path once the other process is finished revoking.
          Secondly, the bias process could have acquired or released
          the biaslock field; in this case we need merely retry. */
          status = L->lockword.h.status;
       }
       while (ISBIASED(L->lockword.h.status));
     }

     /* If I get here, the lock has been revoked by someone other
     than me. Wait until they’re done revoking, then fall through
     to the default code. */
     while (DEFAULT != L->lockword.h.status)
     ;
   }

     /* Regular default lock from here on */
     assert(DEFAULT == L->lockword.h.status);
     /* *** DO NORMAL (CONTENDED) DEFAULT LOCK ACQUIRE FUNCTION HERE *** */
     return 0;
  }

  void qrlgeneric_release(qrlgeneric_lock *L, int acquiredquickly)
  {
     if (acquiredquickly)
     L->lockword.h.quicklock = 0;
     else
     {
     /* *** DO NORMAL DEFAULT LOCK RELEASE FUNCTION HERE *** */
     }
  }
qrl锁的状态*/ #定义偏差(id)((int)(id)16)) typedef volatile结构标记\u qrlgeneric\u锁 { 易变联 { 挥发性结构 { 易变短快锁; 波动性短状态; } H 易失性int数据; } 锁字; /****加上默认锁所需的任何字段****/ } qrlgeneric_锁; int qrlgeneric_acquire(qrlgeneric_lock*L,int id) { int status=L->lockword.h.status; /*如果锁是我的,我只需设置一个标志就可以重新进入*/ if(偏置(id)=状态) { L->lockword.h.quicklock=1; if(偏置(id)=高位字(L->lockword.data)) 返回1; L->lockword.h.quicklock=0;/*我没有得到锁,所以请确定*/ /*而不是阻止这样做的过程*/ } 如果(默认!=状态) { /*如果锁是无人拥有的,试着认领它*/ 如果(空档==状态) { 如果我们看到*/ MAKEDWORD(0,空档),/*空档,锁未接合*/ MAKEDWORD(1,有偏(id))) { 返回1; } /*如果我没有把锁偏向我,其他人就会抓住 它。通过撤销代码*/ status=L->lockword.h.status;/*重新采样*/ } /*如果锁归其他人所有,请将其吊销*/ 如果(ISBIASED(状态)) { 做 { 无符号短biaslock=L->lockword.h.quicklock; 如果(CAS&L->lockword, 马克德沃德(比亚斯洛克,地位), 马克德沃德(比亚斯洛克,撤销))) { /*我是撤销者。设置默认锁*/ /****在此处初始化并获取默认锁****/ /*注意:这是一个非竞争性收购,因此*/ /*如果需要,可以不使用原子来完成*/ /*可取的*/ L->lockword.h.status=默认值; /*等待quicklock释放*/ while(LOWWORD(L->lockword.data)) ; 返回0;/*则它是我的*/ } /*CAS可能会失败,我们来这里是为了 有两个原因。第一,另一个过程可以做到这一点 撤销;在这种情况下,我们需要通过 另一个进程完成撤销后的默认路径。 其次,偏差过程可能已经获得或释放 biaslock字段;在这种情况下,我们只需重试*/ status=L->lockword.h.status; } 而(ISBIASED(L->lockword.h.status)); } /*如果我到了这里,锁已经被其他人撤销了 而不是我。等他们撤销后,就失败了 设置为默认代码*/ while(默认值!=L->lockword.h.status) ; } /*从此处开始使用常规默认锁*/ 断言(默认==L->lockword.h.status); /****此处执行正常(争用)默认锁获取功能****/ 返回0; } 无效qrlgeneric_释放(qrlgeneric_lock*L,int快速获取) { 如果(快速获得) L->lockword.h.quicklock=0; 其他的 { /****此处执行正常默认锁释放功能***