我偶然发现了 the following Code Review StackExchange并决定阅读它作为练习。在代码中,有以下内容:
注意:我不是在寻找代码审查,这只是链接中代码的复制粘贴,因此您可以专注于手头的问题,而无需其他代码干扰。我对实现“智能指针”不感兴趣,只是了解内存模型:
// Copied from the link provided (all inside a class)
unsigned int count;
mutex m_Mutx;
void deref()
{
m_Mutx.lock();
count--;
m_Mutx.unlock();
if (count == 0)
{
delete rawObj;
count = 0;
}
}
看到这个让我立即想到“如果两个线程在 count == 1 时进入并且都看不到彼此的更新怎么办?最终都可以将 count 视为零和双重删除?两个线程是否有可能导致 count 变为 -1,然后删除永远不会发生?
互斥量将确保一个线程进入临界区,但这是否保证所有线程都将被正确更新? C++ 内存模型告诉我什么,所以我可以判断这是否是竞争条件?
我查看了 Memory model cppreference page和 std::memory_order cppreference ,但是后一页似乎处理原子参数。我没有找到我要找的答案,或者我看错了。谁能告诉我我说的是错还是对,这段代码是否安全?
如果代码损坏,请更正代码:
将计数转换为原子成员的正确答案是这个吗?或者这是否有效,并且在释放互斥体上的锁后,所有线程都看到了该值?
我也很好奇这是否会被视为正确答案:
注意:我不是在寻找代码审查,也不是想看看这种解决方案是否能解决与 C++ 内存模型相关的问题。
#include <atomic>
#include <mutex>
struct ClassNameHere {
int* rawObj;
std::atomic<unsigned int> count;
std::mutex mutex;
// ...
void deref()
{
std::scoped_lock lock{mutex};
count--;
if (count == 0)
delete rawObj;
}
};
最佳答案
“如果两个线程在计数 == 1 时进入怎么办”——如果发生这种情况,则其他事情很可疑。智能指针背后的想法是引用计数绑定(bind)到对象的生命周期(范围)。递减发生在对象(通过堆栈展开)被销毁时。如果两个线程触发它,除非存在另一个错误,否则引用计数不可能仅为 1。
但是,当 count = 2 时,可能会发生两个线程输入此代码的情况。在那种情况下,递减操作被互斥锁锁定,因此它永远不会达到负值。同样,这假设其他地方没有错误代码。由于所有这一切只是删除对象(然后冗余地将计数设置为零),所以不会发生任何不好的事情。
虽然可能会发生双重删除。如果 count = 2 处的两个线程递减计数,之后它们都可以看到 count = 0。只需确定是否删除互斥量内的对象作为简单修复即可。将该信息存储在局部变量中,并在释放互斥锁后进行相应处理。
关于您的第三个问题,将计数转换为原子并不能神奇地解决问题。此外,原子背后的要点是您不需要需要互斥量,因为锁定互斥量是一项昂贵的操作。使用原子,您可以结合递减和检查零等操作,这类似于上面提出的修复。原子通常比“普通”整数慢。不过它们仍然比互斥体快。
关于C++ 成员在非原子时更新关键部分内的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54173168/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我正在编写一个方法,它将在一个类中定义一个实例方法;类似于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
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我正在尝试学习Ruby词法分析器和解析器(whitequarkparser)以了解更多有关从Ruby脚本进一步生成机器代码的过程。在解析以下Ruby代码字符串时。defadd(a,b)returna+bendputsadd1,2它导致以下S表达式符号。s(:begin,s(:def,:add,s(:args,s(:arg,:a),s(:arg,:b)),s(:return,s(:send,s(:lvar,:a),:+,s(:lvar,:b)))),s(:send,nil,:puts,s(:send,nil,:add,s(:int,1),s(:int,3))))任何人都可以向我解释生成的
这太简单了,太荒谬了,我在任何地方都找不到关于它的任何信息,包括API文档和Rails源代码:我有一个:belongs_to关联,我开始理解当您没有关联时您在Controller中调用的正常模型方法与您有关联时调用的方法略有不同。例如,我的关联在创建Controller操作时运行良好:@user=current_user@building=Building.new(params[:building])respond_todo|format|if@user.buildings.create(params[:building])#etcetera但我找不到关于更新如何工作的文档:@user