char代替std :: atomic_flag或std :: atminc_bool

时间:2018-08-30 09:04:41

标签: c++

我想知道是否可以使用

char Flag;

代替

std::atomic_flag Flag;

我知道,一般而言,C ++基本类型不是原子/线程安全的(这就是std::atomic存在的原因),但是我也知道char的大小始终为1个字节。而且我无法想象单字节读/写不是线程安全的情况。

我也找不到关于char变量的线程安全性的任何信息。

考虑以下示例(Win32,Visual Studio 2015,发行版,禁用优化):

// Can be any integral type
using mytype_t = unsigned char;

#define VAL1 static_cast<mytype_t>(0x5555555555555555ULL)
#define VAL2 static_cast<mytype_t>(0xAAAAAAAAAAAAAAAAULL)

#define CYCLES (50 * 1000 * 1000)

void runtest_mytype()
{
    //  Just to stop checking thread
    std::atomic_bool Stop = false;

    const auto Started = ::GetTickCount64();

    auto Val = VAL1;

    std::thread threadCheck([&]()
    {
        //  Checking values
        while (!Stop)
        {
            const auto Val_ = Val;
            if (VAL1 != Val_ && VAL2 != Val_)
                std::cout << "Error! " << std::to_string(Val_) << std::endl;
        }
    });

    std::thread thread1([&]()
    {
        for (auto I = 0; I < CYCLES; ++I)
            Val = VAL1;
    });

    std::thread thread2([&]()
    {
        for (auto I = 0; I < CYCLES; ++I)
            Val = VAL2;
    });

    thread1.join();
    thread2.join();
    std::cout << "mytype: finished in " << std::to_string(::GetTickCount64() - Started) << " ms" << std::endl;

    Stop = true;
    threadCheck.join();
}

void runtest_atomic_flag()
{
    std::atomic_flag Flag;

    const auto Started = ::GetTickCount64();

    std::thread thread1([&]()
    {
        for (auto I = 0; I < CYCLES; ++I)
            auto Val_ = Flag.test_and_set(std::memory_order_acquire);
    });

    std::thread thread2([&]()
    {
        for (auto I = 0; I < CYCLES; ++I)
            Flag.clear(std::memory_order_release);
    });

    thread1.join();
    thread2.join();
    std::cout << "atomic_flag: finished in " << std::to_string(::GetTickCount64() - Started) << " ms" << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    runtest_mytype();
    runtest_atomic_flag();

    std::getchar();

    return 0;
}

它输出类似这样的内容(在几次测试中,这些值没有太大变化):

mytype: finished in 312 ms
atomic_flag: finished in 1669 ms

因此,char而不是atomic_flag的运行速度显着提高,在某些情况下可以发挥作用。

但是我与std::atomiс_flag的发明是徒劳的。

请帮我弄清楚。至少,当我仅使用Windows,仅使用Visual Studio并且不需要考虑兼容性时,我可以使用char吗?

1 个答案:

答案 0 :(得分:0)

原子变量的更改在其他线程中也可见。

使用char时,其他线程可能看不到该修改(这就是为什么某些人错误地使用volatile进行同步)。

顺便说一句,在不同步的情况下同时修改char是UB。