亚马逊文档(http://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html#ConsistencyModel)声明:
"Amazon S3为所有地区的S3存储桶中的新对象的PUTS提供了写后读写一致性,但有一点需要注意."
忽略警告,这意味着在PUT之后为新对象发出GET的客户端可以保证获得正确的结果.我的问题是,如果GET是从不同的客户端而不是PUT的那个客户端发出的,那么保证是否也适用(当然,假设GET按照时间顺序跟随PUT)?换句话说,读写后一致性只是读写一致性还是适用于所有客户端?
我怀疑答案是它在全球范围内有效,但无法找到明确的答案.
下面我有一个名为ProxyCall的模板函数,它接受一个对象,一个成员函数及其参数.它只是将调用转发给成员函数.
我希望能够在不使用模板限定符的情况下调用该函数(想象大量此类调用具有多个参数).当我尝试传递const引用参数时,类型推导主要起作用,但编译器(msvc和gcc 4.9)都是barf.
#include <string>
struct Widget {
void f(const std::string& s, bool b) {}
};
template<typename T, typename... Args>
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) {
(obj.*method)(std::forward<Args>(args)...);
}
int main(int argc, char* argv[])
{
Widget w;
std::string s;
ProxyCall<Widget, const std::string&, bool>(w, &Widget::f, s, true); // OK
ProxyCall(w, &Widget::f, (const std::string&)s, true); // also OK
ProxyCall(w, &Widget::f, s, true); // ERROR: template parameter is ambiguous
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何修改上面的代码,以便编译器自动推导出类型,而无需借助显式模板限定符或显式转换.考虑到编译器已经从Widget :: f的签名中知道确切的参数类型,这似乎应该是可能的.
我错误地认为atomic :: load也应该充当内存屏障,确保所有先前的非原子写入将被其他线程看到?
为了显示:
volatile bool arm1 = false;
std::atomic_bool arm2 = false;
bool triggered = false;
Run Code Online (Sandbox Code Playgroud)
线程1:
arm1 = true;
//std::std::atomic_thread_fence(std::memory_order_seq_cst); // this would do the trick
if (arm2.load())
triggered = true;
Run Code Online (Sandbox Code Playgroud)
线程2:
arm2.store(true);
if (arm1)
triggered = true;
Run Code Online (Sandbox Code Playgroud)
我预计在执行两个'触发'之后都是真的.请不要建议使arm1原子,重点是探索atomic :: load的行为.
虽然我不得不承认我并不完全理解内存顺序的不同松弛语义的正式定义,但我认为顺序一致的顺序非常简单,因为它保证"存在单个总顺序,其中所有线程都观察到所有修改以相同的顺序." 对我来说,这意味着std :: atomic :: load与默认内存顺序std :: memory_order_seq_cst也将充当内存栅栏."顺序一致排序"下的声明进一步证实了这一点:
总顺序排序需要在所有多核系统上使用完整的内存栅栏CPU指令.
然而,我下面的简单示例演示了MSVC 2013,gcc 4.9(x86)和clang 3.5.1(x86)的情况并非如此,其中原子载荷只是转换为加载指令.
#include <atomic>
std::atomic_long al;
#ifdef _WIN32
__declspec(noinline)
#else
__attribute__((noinline))
#endif
long load() {
return al.load(std::memory_order_seq_cst);
}
int main(int …Run Code Online (Sandbox Code Playgroud) 我们知道 Amazon S3 为大多数操作提供最终一致性,但有不同类型的最终一致性。一种特定形式是单调读取一致性,其定义为:
“如果进程看到了对象的特定值,则任何后续访问都将永远不会返回任何先前的值”
因此,如果我执行 PUT 来覆盖一个对象并在一段时间后获取新数据,我是否可以保证一旦我看到新值,后续 GET 就不会看到旧值?