如果我在子函数中放置内存栅栏,而不是在使用数据的函数中放置内存围栏,那么线程安全性是否存在差异。下面的示例包括这两个版本。我想知道是否有我不知道的分歧。函数A_function和B_function是否都是线程安全?
#include<atomic>
using std::atomic;
using std::atomic_thread_fence;
using std::memory_order_acquire;
using std::memory_order_release;
typedef struct
{
atomic<int> lock;
int counter;
}Data;
void A_acquire(atomic<int> * lock);
void A_release(atomic<int> * lock);
void A_function(Data * data);
void B_acquire(atomic<int> * lock);
void B_release(atomic<int> * lock);
void B_function(Data * data);
void A_acquire(atomic<int> * lock)
{
int ticket = lock->fetch_add(1);
while (0 != ticket)
{
lock->fetch_sub(1);
ticket = lock->fetch_add(1);
}
//DIFFERENCE HERE
}
void A_release(atomic<int> * lock)
{
//DIFFERENCE HERE
lock->fetch_sub(1);
}
void A_function(Data * data)
{
A_acquire(&data->lock);
atomic_thread_fence(std::memory_order_acquire); //DIFFERENCE HERE
data->counter += 1;
atomic_thread_fence(std::memory_order_release); //DIFFERENCE HERE
A_release(&data->lock);
}
void B_acquire(atomic<int> * lock)
{
int ticket = lock->fetch_add(1);
while (0 != ticket)
{
lock->fetch_sub(1);
ticket = lock->fetch_add(1);
}
atomic_thread_fence(std::memory_order_acquire); //DIFFERENCE HERE
}
void B_release(atomic<int> * lock)
{
atomic_thread_fence(std::memory_order_release); //DIFFERENCE HERE
lock->fetch_sub(1);
}
void B_function(Data * data)
{
B_acquire(&data->lock);
//DIFFERENCE HERE
data->counter += 1;
//DIFFERENCE HERE
B_release(&data->lock);
}
int main(void)
{
Data dat = { 0, 0 };
A_function(&dat);
B_function(&dat);
return 0;
}发布于 2015-04-30 22:32:12
A_function和B_function在语义上没有区别。记忆栅栏效应不受函数体的限制。
另外,正如幻影所指出的,在您的示例中,内存围栏是不必要的:fetch_sub()和fetch_add()都已经获得+发布语义。
但是通过下面的修改,版本获取变得非常重要:
void A_acquire(atomic<int> * lock)
{
int ticket = lock->exchange(1);
while (0 != ticket)
{
ticket = lock->exchange(1);
}
//DIFFERENCE HERE
}
void A_release(atomic<int> * lock)
{
//DIFFERENCE HERE
lock->store(0, memory_order_relaxed);
}https://stackoverflow.com/questions/29977679
复制相似问题