C 可快速获取的锁
这是一种在两个或更多线程真正访问关键部分之前不使用OS同步原语的算法。即使在同一个线程的递归“锁”中,在涉及第二个线程之前也没有真正的锁 有两个功能: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
int qrlgeneric_acquire(qrlgeneric_lock *L, int id);
void qrlgeneric_release(qrlgeneric_lock *L, int acquiredquickly);
qrlgeneric\u acquire:在线程想要锁定时调用<代码>id是线程idqrlgeneric\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。此条件将成功,因为点1和3不会对其产生影响
结果是我认为它们都可以成功,但这意味着线程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;
其他的
{
/****此处执行正常默认锁释放功能***