我试着寻找这方面的细节,我什至阅读了关于互斥锁和原子的标准......但我仍然无法理解 C++11 内存模型可见性保证。 据我了解,互斥互斥的非常重要的特性是确保可见性。也就是每次只有一个线程增加计数器是不够的,重要的是线程增加最后使用互斥锁的线程存储的计数器(我真的不知道为什么人们在讨论时不提这个互斥体,也许我有不好的老师:))。 因此,据我所知, atomic 不会强制立即可见: (来自维护 boost::thread 并实现了 c++11 线程和互斥库的人):
A fence with memory_order_seq_cst does not enforce immediate visibility to other threads (and neither does an MFENCE instruction). The C++0x memory ordering constraints are just that --- ordering constraints. memory_order_seq_cst operations form a total order, but there are no restrictions on what that order is, except that it must be agreed on by all threads, and it must not violate other ordering constraints. In particular, threads may continue to see "stale" values for some time, provided they see values in an order consistent with the constraints.
我同意。但问题是我很难理解关于原子的 C++11 构造是“全局的”,并且只能确保原子变量的一致性。 特别是,我了解以下哪些(如果有)内存排序保证在加载和存储之前和之后会有一个内存栅栏: http://www.stdthread.co.uk/doc/headers/atomic/memory_order.html
据我所知,std::memory_order_seq_cst 插入了内存屏障,而其他只强制对特定内存位置的操作进行排序。
所以有人可以澄清一下吗,我想很多人会使用 std::atomic 制造可怕的错误,尤其是如果他们不使用默认值(std::memory_order_seq_cst 内存排序)
2.如果我是对的,这是否意味着此代码中的第二行是多余的:
atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
3。从某种意义上说,std::atomic_thread_fences 是否与互斥锁具有相同的要求,以确保非原子变量的 seq 一致性必须执行 std::atomic_thread_fence(std::memory_order_seq_cst);
加载前和
std::atomic_thread_fence(std::memory_order_seq_cst);
在商店之后?
4.是
{
regularSum+=atomicVar.load();
regularVar1++;
regularVar2++;
}
//...
{
regularVar1++;
regularVar2++;
atomicVar.store(74656);
}
相当于
std::mutex mtx;
{
std::unique_lock<std::mutex> ul(mtx);
sum+=nowRegularVar;
regularVar++;
regularVar2++;
}
//..
{
std::unique_lock<std::mutex> ul(mtx);
regularVar1++;
regularVar2++;
nowRegularVar=(74656);
}
我认为不是,但我想确定一下。
编辑:
5.
能断言火吗?
只有两个线程存在。
atomic<int*> p=nullptr;
第一个线程写入
{
nonatomic_p=(int*) malloc(16*1024*sizeof(int));
for(int i=0;i<16*1024;++i)
nonatomic_p[i]=42;
p=nonatomic;
}
第二个线程读取
{
while (p==nullptr)
{
}
assert(p[1234]==42);//1234-random idx in array
}
最佳答案
如果你喜欢处理栅栏,那么 a.load(memory_order_acquire) 相当于 a.load(memory_order_relaxed) 后跟 atomic_thread_fence(memory_order_acquire) 。类似地,a.store(x,memory_order_release) 相当于在调用 a.store(x,memory_order_relaxed)< 之前调用="">。 atomic_thread_fence(memory_order_release)/memory_order_consume 是 memory_order_acquire 的一个特例,仅用于相关数据。 memory_order_seq_cst 是特殊的,它构成了所有 memory_order_seq_cst 操作的总顺序。与其他混合,它与加载的获取和存储的释放相同。 memory_order_acq_rel用于read-modify-write操作,相当于RMW的read部分的acquire和write部分的release。
对原子操作使用排序约束可能会也可能不会产生实际的栅栏指令,具体取决于硬件架构。在某些情况下,如果您将排序约束放在原子操作上而不是使用单独的栅栏,编译器会生成更好的代码。
在 x86 上,加载始终是获取的,而存储始终是释放的。 memory_order_seq_cst 需要使用 MFENCE 指令或 LOCK 前缀指令进行更强的排序(这里有一个实现选择,是否使存储具有更强的排序或负载)。因此,独立的获取和释放栅栏是无操作的,但 atomic_thread_fence(memory_order_seq_cst) 不是(再次需要 MFENCE 或 LOCK ed 指令) .
排序约束的一个重要影响是它们对其他操作进行排序。
std::atomic<bool> ready(false);
int i=0;
void thread_1()
{
i=42;
ready.store(true,memory_order_release);
}
void thread_2()
{
while(!ready.load(memory_order_acquire)) std::this_thread::yield();
assert(i==42);
}
thread_2 旋转直到它从 ready 读取 true。由于在 thread_1 中存储到 ready 是一个释放,并且加载是一个获取,因此存储 同步 加载,并且存储到 i happens-before 在断言中从 i 加载,并且断言不会触发。
2)
中的第二行atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
确实可能冗余,因为存储到 atomicVar 默认使用 memory_order_seq_cst。但是,如果此线程上有其他非memory_order_seq_cst 原子操作,则栅栏可能会产生后果。例如,它将充当后续 a.store(x,memory_order_relaxed) 的释放栅栏。
3) 栅栏和原子操作不像互斥锁那样工作。您可以使用它们来构建互斥锁,但它们不像它们那样工作。您不必使用 atomic_thread_fence(memory_order_seq_cst)。不要求任何原子操作都是 memory_order_seq_cst,并且可以在没有的情况下实现对非原子变量的排序,如上例所示。
4) 不,这些不相等。因此,没有互斥锁的代码段是数据竞争和未定义的行为。
5) 不,您的断言不能触发。使用 memory_order_seq_cst 的默认内存顺序,来自原子指针 p 的存储和加载就像我上面示例中的存储和加载一样工作,并且保证在读取之前发生对数组元素的存储.
关于c++ - 内存模型排序和可见性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7461484/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:
我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs