0

データが使用される関数ではなく、サブ関数にメモリ フェンスを配置した場合、スレッド セーフに違いはありますか。一番下の例には、両方のバージョンが含まれています。私が気づいていない違いがあるのだろうか。関数A_functionB_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;
}
4

1 に答える 1

2

と の間に意味的な違いはありませA_functionB_function。メモリ フェンス効果は、関数の本体によって制限されません。

fetch_sub()また、Phantom が指摘しているように、あなたの例のメモリ フェンスは不要です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);
}
于 2015-04-30T22:32:12.573 に答える