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 unlocksstore(0,release)
要么在设置为1之前发生,因此锁由新线程获取,要么在新线程未能获取锁之后发生。显然,只有拥有互斥锁的线程才能尝试解锁它
我在这里遗漏了什么,或者你能用这种方式创建互斥吗?有趣的是,如果标志仅为一个位(例如指针或整数),则fetch_或mutex会更好地工作。使用经典的交换技术,您首先需要加载,这样就不会对值造成冲击,并且可能需要使用比较和交换而不是交换,这取决于您对互斥字中的值所做的操作。fetch\u或是有吸引力的,因为它只会修改字中的互斥标志位。是,
fetch\u或(1)
相当于exchange(1)
,如果可能的值是0和1。请注意,在x86上,当需要返回值时,C++11fetch\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++11fetch\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)
的结果,只要使用常量执行或。