jjzjj

c++ - std::atomic 访问是否作为内存屏障?

coder 2024-02-04 原文

编译器能否对原子指令重新排序,或者原子指令是否充当内存屏障? 再说一遍,写在原子指令之后的指令能在原子指令之前执行吗?

请看下面的代码。如果 useMapA = falsemapB 更新和读取线程开始之前移动,我们将使用无效的 mapB

注意:更新线程每 15 分钟才发生一次,因此我们有一个非常好的结构化流程,以及避免使用昂贵的锁定调用的方法!

std::atomic<bool> useMapA;
std::map<string, string> mapA, mapB;

public void updateMap(map<string, string>* latestMap) {
    if (useMapA) {
        mapB = std::move(*latestMap);
        useMapA = false;
    } else {
        mapA = std::move(*latestMap);
        useMapA = true;
    }
}

inline map<string, string>& getMap() {
    return useMapA ? mapA : mapB;
}

编辑:我有兴趣以 100% 线程安全换取速度(时间 = 金钱)。这个读取函数需要运行得非常快。您可以假设 15 分钟足够长,以避免如果这个时间短得多会导致的竞争条件。

最佳答案

在回答您的问题之前,我想向您展示如何使用 std::shared_ptr原子操作 轻松实现该功能。以下实现是高效且线程安全的。 读者也不需要创建 map 的拷贝。

using string_map = std::map<std::string, std::string>;

std::shared_ptr<const string_map> map;

std::shared_ptr<const string_map> getMap()
{
    return std::atomic_load(&map);
}

void updateMap(string_map latestMap)
{
    std::shared_ptr<const string_map> temp{
        new string_map{std::move(latestMap)}};
    std::atomic_store(&map, temp);
}

现在,让我们看一下您的代码。这有点复杂。为了方便起见,我们假设 updateMap 每秒调用一次,而不是每 15 分钟调用一次。 useMapA 最初是 true。更新线程执行以下语句,并在更新原子标志之前被中断:

if (useMapA) {
    mapB = std::move(*latestMap);

现在,读取器线程只评估原子标志:

bool r1 = useMapA; // r1==true

更新线程继续并将原子标志设置为false。一秒钟后,更新线程评估原子标志:

if (useMapA) { // condition is false

现在,读者线程继续。两个线程都访问 mapA,并且至少有一个线程写入数据结构。这意味着存在数据竞争,这意味着程序的行为是未定义的,无论这种数据竞争是否真的发生。

如果 updateMap 每 15 分钟调用一次,会有什么变化?除非在这 15 分钟内发生一些额外的同步,否则它仍然是一场数据竞赛,因为 C++ 标准在一秒和 15 分钟之间没有区别。

关于c++ - std::atomic 访问是否作为内存屏障?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23002097/

有关c++ - std::atomic 访问是否作为内存屏障?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  9. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  10. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

随机推荐