我正在用 C++ 编写一个用于数据缓存的模板库,其中可以进行并发读取和并发写入,但不是针对同一个键。该模式可以用以下环境来解释:
这样,如果线程从缓存中请求一个键但不存在,则可以为该唯一键启动锁定计算。与此同时,其他线程可以检索或计算其他键的数据,但试图访问第一个键的线程会被锁定等待。
主要的约束是:
我的其他限制但已经解决的是:
我不确定为每个键使用 1 个互斥锁是实现此目的的正确方法,但我没有发现任何其他有本质区别的方法。
您是否知道实现此功能的其他模式,或者您认为这是一个合适的解决方案?我不喜欢拥有大约 100 个互斥量的想法。 (缓存大小约为 100 个键)
最佳答案
你想锁定,你想等待。因此,某处应该有“条件”(如类 Unix 系统上的 pthread_cond_t)。
我建议如下:
当线程希望从缓存中获取值时,它首先获取全局互斥锁。然后它在 map 中查找:
在伪代码中,它看起来像这样:
mutex_t global_mutex
hashmap_t map
lock(global_mutex)
w = map.get(key)
if (w == NULL) {
w = new Wrapper
map.put(key, w)
unlock(global_mutex)
v = compute_value()
lock(global_mutex)
w.set(v)
signal(w.cond)
unlock(global_mutex)
return v
} else {
v = w.get()
while (v == NULL) {
unlock-and-wait(global_mutex, w.cond)
v = w.get()
}
unlock(global_mutex)
return v
}
在pthreads术语中,lock是pthread_mutex_lock(),unlock是pthread_mutex_unlock(),unlock-and-wait 是 pthread_cond_wait() 和 signal 是 pthread_cond_signal()。 unlock-and-wait 原子地释放互斥量并将线程标记为等待条件;当线程被唤醒时,互斥量会自动重新获取。
这意味着每个包装器都必须包含一个条件。这体现了您的各种要求:
请注意,当一个线程希望获取一个值并发现其他线程已经在忙于计算它时,线程最终会锁定全局互斥锁两次:一次在开始时,一次在该值可用时。一个更复杂的解决方案,每个包装器有一个互斥体,可以避免第二次锁定,但除非争用非常高,否则我怀疑这样做是否值得。
关于拥有多个互斥量:互斥量很便宜。互斥量基本上是一个 int,它的成本不超过用于存储它的四个左右字节的 RAM。注意 Windows 术语:在 Win32 中,我在这里所说的互斥量被认为是“互锁区域”;当 CreateMutex() 被调用时 Win32 创建的是完全不同的东西,它可以从几个不同的进程访问,并且因为它涉及到内核的往返而更昂贵。请注意,在 Java 中,每个单独的对象实例都包含一个互斥量,并且 Java 开发人员在这个问题上似乎并不过分脾气暴躁。
关于c++ - C++ 线程安全对象缓存的设计选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2139724/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数