我在中使用SunOs提供的原子操作,它是
void *atomic_cas_ptr(volatile void *target, void *cmp, void *newval);
现在为了使其可用,我必须检查这个函数返回的旧值和被调用函数cmp传递的旧值是否相同,如果是,则操作是否成功。
但我有一定的疑问:因为这个函数返回一个指向旧值的void指针,我们称它为void *old,我传递了void *cmp,那么我需要比较这两个old和cmp,那么我该如何比较这两个呢?如果在比较的时候,旧的改变了,那我该怎么办?
本质上,我想要做的是扭曲这个函数,在另一个函数中,这个函数接受这三个参数,并返回true或false,表示成功或失败。
关于CAS,我读到称它为无锁操作是用词不当,因为它最终会在硬件上锁定(在总线上锁定),对吗?这就是为什么CAS的运营成本很高。
发布于 2011-06-19 04:11:35
可能是函数声明把您弄糊涂了。此函数不返回指向旧值(什么的?)的指针,而是返回由target指向的内存中的旧值(实际上应该是指向void* volatile * target*的指针)。
通常,如果CAS原语返回的是旧值而不是布尔值,则可以使用以下内容检查CAS是否成功:
void* atomic_ptr; // global atomically modified pointer
void* oldval, newval, comparand; // local variables
/* ... */
oldval = atomic_cas_ptr( (void*)&atomic_ptr, /* note that address is taken */
comparand, newval );
if( oldval == comparand ) {
// success
} else {
// failure
}因此,当您比较old_val和compare时,您使用的是不会并发更改的局部变量(而全局atomic_ptr可能会再次更改),并且您可以在不取消引用的情况下比较指针值。
你想要的函数应该是这样的:
bool my_atomic_cas_ptr(volatile void* target, void* comparand, void* newval)
{
return (comparand == atomic_cas_ptr(target, comparand, newval));
}请注意,因为在某些算法中旧值(在CAS之前的值)应该是已知的,所以最好让CAS原语返回旧值而不是布尔值,因为您可以很容易地从前者构建后者,而从前者构建后者则更加复杂和低效(请参阅下面的代码,该代码试图从返回布尔值的a MacOS CAS primitive中获取正确的旧值)。
void* CAS(void* volatile* target, void* comparand, void* newval)
{
while( !OSAtomicCompareAndSwapPtr(comparand, newval, target) ) {
void* snapshot = *target;
if( snapshot!=comparand ) return snapshot;
}
return comparand;
}至于CAS锁定内存总线,则依赖于硬件。这对于旧的x86处理器是正确的,但在现代x86系统中是不同的。首先,没有中央总线,取而代之的是AMD的HyperTransport和英特尔的QuickPath互连。其次,在最近几代CPU中,锁定指令并不都是序列化的(参见some data显示不同内存地址上的锁定指令不会干扰)。最后,在the commonly accepted definition中,锁自由是系统级进程的保证,而不是缺少serializing synchronization。
https://stackoverflow.com/questions/6385063
复制相似问题