C++ 使用锁位或(fetch_或)创建互斥锁?

C++ 使用锁位或(fetch_或)创建互斥锁?,c++,c,locking,lock-free,C++,C,Locking,Lock Free,如果你只有一个原子操作,你可以创建一个互斥锁吗 我想是的。经典算法使用lock xchg和一个整数标志,其中1表示锁定状态,0表示解锁状态。因此,在标记上原子地交换(1),如果前面返回的值为0,则您拥有互斥锁,否则无法获取互斥锁。释放一个拥有的互斥锁只需释放存储0即可 您可以对fetch_或(1)执行相同的操作,这会将标志设置为1,并在以前为0或1时返回。至关重要的是,与exchange操作一样,如果值已经为1,则不会修改它 在这两种情况下,racing unlocksstore(0,relea

如果你只有一个原子操作,你可以创建一个互斥锁吗

我想是的。经典算法使用
lock xchg
和一个整数标志,其中1表示锁定状态,0表示解锁状态。因此,在标记上原子地交换(1),如果前面返回的值为0,则您拥有互斥锁,否则无法获取互斥锁。释放一个拥有的互斥锁只需释放存储0即可

您可以对fetch_或(1)执行相同的操作,这会将标志设置为1,并在以前为0或1时返回。至关重要的是,与exchange操作一样,如果值已经为1,则不会修改它

在这两种情况下,racing unlocks
store(0,release)
要么在设置为1之前发生,因此锁由新线程获取,要么在新线程未能获取锁之后发生。显然,只有拥有互斥锁的线程才能尝试解锁它


我在这里遗漏了什么,或者你能用这种方式创建互斥吗?有趣的是,如果标志仅为一个位(例如指针或整数),则fetch_或mutex会更好地工作。使用经典的交换技术,您首先需要加载,这样就不会对值造成冲击,并且可能需要使用比较和交换而不是交换,这取决于您对互斥字中的值所做的操作。fetch\u或是有吸引力的,因为它只会修改字中的互斥标志位。

是,
fetch\u或(1)
相当于
exchange(1)
,如果可能的值是0和1。请注意,在x86上,当需要返回值时,C++11
fetch\u或
必须使用
lock cmpxchg
retry循环来实现。是的,你可以只使用一个大整数的一个位。你可以直接用CAS来交换
old | 1
@PeterCordes哦,这不符合目的。原子库愚弄了我,使我误以为有一条真正的指令执行
原子或
,返回先前的值。当然,当
返回操作结果时,向其添加
前缀不会影响该操作。因此,它当然必须被模仿。这既回答了我的问题,也回答了我的提问动机。
lock或[mem],reg
只返回结果。您只需了解目的地现在是非零还是负,以及低字节的奇偶校验
fetch_或
之所以存在,是因为某些ISA可能具有此功能,而LL/SC计算机可以像任何其他原子RMW一样执行此功能。x86只有
lock xadd
用于
fetch\u add
xchg
用于
exchange
,除非您不使用返回值,否则其他东西必须执行
lock cmpxchg
。没错,我已经有一段时间没有在汇编中编程了。如果在互斥字中设置符号位,仍然可以使用互斥的标志结果,但只能在某些假设的体系结构中使用,其中它返回指令之前的值,而不是编译时程序员已经知道的
或(msb)
的结果,只要使用常量执行
,如果可能的值为0和1,
fetch\u或(1)
相当于
exchange(1)
。请注意,在x86上,当需要返回值时,C++11
fetch\u或
必须使用
lock cmpxchg
retry循环来实现。是的,你可以只使用一个大整数的一个位。你可以直接用CAS来交换
old | 1
@PeterCordes哦,这不符合目的。原子库愚弄了我,使我误以为有一条真正的指令执行
原子或
,返回先前的值。当然,当
返回操作结果时,向其添加
前缀不会影响该操作。因此,它当然必须被模仿。这既回答了我的问题,也回答了我的提问动机。
lock或[mem],reg
只返回结果。您只需了解目的地现在是非零还是负,以及低字节的奇偶校验
fetch_或
之所以存在,是因为某些ISA可能具有此功能,而LL/SC计算机可以像任何其他原子RMW一样执行此功能。x86只有
lock xadd
用于
fetch\u add
xchg
用于
exchange
,除非您不使用返回值,否则其他东西必须执行
lock cmpxchg
。没错,我已经有一段时间没有在汇编中编程了。如果在互斥字中设置符号位,仍然可以使用互斥的标志结果,但只能在某些假设的体系结构中使用,其中它返回指令之前的值,而不是编译时程序员已经知道的
或(msb)
的结果,只要使用常量执行