假设:
A. WIN32下的C++。
B.使用 InterlockedIncrement() 和 InterlockedDecrement() 递增和递减的正确对齐的 volatile 整数。
__declspec (align(8)) volatile LONG _ServerState = 0;
如果我想简单地读取 _ServerState,是否需要通过 InterlockedXXX 函数读取变量?
例如,我见过这样的代码:
LONG x = InterlockedExchange(&_ServerState, _ServerState);
和
LONG x = InterlockedCompareExchange(&_ServerState, _ServerState, _ServerState);
目标是简单地读取 _ServerState 的当前值。
我不能简单地说:
if (_ServerState == some value)
{
// blah blah blah
}
这个主题似乎有些困惑。我知道寄存器大小的读取在 Windows 中是原子的,所以我认为 InterlockedXXX 函数是不必要的。
马特·J。
好的,感谢您的回复。顺便说一句,这是 Visual C++ 2005 和 2008。
如果是真的,我应该使用 InterlockedXXX 函数来读取 _ServerState 的值,即使只是为了清楚起见,最好的方法是什么?
LONG x = InterlockedExchange(&_ServerState, _ServerState);
这有修改值的副作用,而我真正想做的就是读取它。不仅如此,如果有上下文切换,我可能会将标志重置为错误的值,因为 _ServerState 的值被压入堆栈以准备调用 InterlockedExchange ().
LONG x = InterlockedCompareExchange(&_ServerState, _ServerState, _ServerState);
我从我在 MSDN 上看到的一个例子中得到了这个。
见 http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx
我所需要的只是一些类似的东西:
lock mov eax, [_ServerState]
无论如何,我认为很清楚的一点是提供对标志的线程安全访问,而不会产生关键部分的开销。我已经看到通过 InterlockedXXX() 系列函数以这种方式使用 LONG,因此我提出了问题。
好的,我们正在考虑一个很好的解决这个读取当前值问题的方法是:
LONG Cur = InterlockedCompareExchange(&_ServerState, 0, 0);
最佳答案
这取决于您所说的“目标是简单地读取 _ServerState 的当前值”的意思,它取决于您使用的工具集和平台(您指定 Win32 和 C++,但不是哪个 C++ 编译器,以及可能很重要)。
如果您只是想读取未损坏的值(即,如果其他处理器将值从 0x12345678 更改为 0x87654321,您的读取将获得这两个值之一,而不是 0x12344321),那么只需读取即可只要变量是就可以了:
volatile, C/C++ 标准没有做出任何 promise ,但 Windows 和 MSVC 确实做出了这些保证,而且我认为大多数针对 Win32 的编译器也是如此。
但是,如果您希望您的读取与其他线程的行为同步,则存在一些额外的复杂性。假设您有一个简单的“邮箱”协议(protocol):
struct mailbox_struct {
uint32_t flag;
uint32_t data;
};
typedef struct mailbox_struct volatile mailbox;
// the global - initialized before wither thread starts
mailbox mbox = { 0, 0 };
//***************************
// Thread A
while (mbox.flag == 0) {
/* spin... */
}
uint32_t data = mbox.data;
//***************************
//***************************
// Thread B
mbox.data = some_very_important_value;
mbox.flag = 1;
//***************************
的想法是线程 A 将旋转等待 mbox.flag 以指示 mbox.data 具有有效的信息。线程 B 将一些数据写入 mailbox.data 然后将 mbox.flag 设置为 1 作为 mbox.data 有效的信号。
在这种情况下,线程 A 中的 mbox.flag 的简单读取可能会获得值 1,即使线程 A 中 mbox.data 的后续读取没有获得线程 B 写入的值。
这是因为即使编译器不会重新排序线程 B 写入 mbox.data 和 mbox.flag 的顺序,处理器和/或缓存也可能会。 C/C++ 保证编译器将生成代码,使得线程 B 在写入 mbox.flag 之前先写入 mbox.data,但处理器和缓存可能有不同的想法 - 称为“内存屏障”或“获取和必须使用“释放语义”来确保低于线程指令流级别的顺序。
我不确定除了 MSVC 之外的编译器是否对指令级别以下的排序做出任何声明。但是,MS 确实保证对于 MSVC volatile 就足够了 - MS 指定 volatile 写入具有释放语义,而 volatile 读取具有获取语义 - 尽管我不确定这适用于哪个版本的 MSVC - 请参阅 http://msdn.microsoft.com/en-us/library/12a04hfd.aspx?ppud=4 。
我还看到像您描述的那样使用互锁 API 对共享位置执行简单读取和写入的代码。我对此事的看法是使用互锁 API。无锁线程间通信充满了非常难以理解和微妙的陷阱,并且试图在可能最终导致非常难以诊断的错误的关键代码位上走捷径对我来说似乎不是一个好主意.此外,使用 Interlocked API 会让任何维护代码的人尖叫,“这是需要与其他东西共享或同步的数据访问 - 小心行事!”。
此外,在使用 Interlocked API 时,您会忽略硬件和编译器的细节 - 平台会确保所有这些东西都得到正确处理 - 不用再怀疑......
阅读 DDJ 上的 Herb Sutter's Effective Concurrency articles(至少对我而言,目前恰好处于关闭状态)以获取有关此主题的详细信息。
关于c++ - 读取互锁变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/779996/
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.
如何将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.你能做的最好的事情是: