繁体   English   中英

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

[英]char instead of std::atomic_flag or std::atminc_bool

我想知道是否可以使用

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是徒劳地发明的想法std::atomiс_flag

请帮我弄清楚。 至少,当我仅使用Windows,仅使用Visual Studio且无需考虑兼容性时,是否可以使用char

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM