|
|
1
6
我认为问题不在于
在我看来,当您为多线程环境编写代码时,已经有足够多的注意事项需要强调,您希望人们不要忽视竞争条件和死锁。
这种包装方法的一个缺点是,包装类型上的每个操作都使用
但是如果你是一个纯粹主义者,相信C++的灵魂。 严格的类型检查 ; 这是一个很好的选择。 |
|
|
2
4
这会捕获某些类型的线程不安全代码(并发访问),但会错过其他代码(由于锁反转而导致的死锁)。两者都不是特别容易测试的,所以这是一个适度的局部胜利。在实践中,记住强制某个特定的私有成员只能在某个指定的锁下访问,这对我来说并不是什么大问题。 这个问题的两个答案表明,你说混淆是一个显著的缺点是正确的——维护人员可能已经非常习惯于理解volatile的内存访问语义与线程安全无关,在声明错误之前,他们甚至不会阅读代码/文章的其余部分。
我认为Alexandrescu在文章中概述的另一个大缺点是,它不适用于非类类型。这可能是一个难以记住的限制。如果你认为标记你的数据成员
我认为数据成员的类型实际上存在任何风险
我想知道,对于通过属性提供额外的const样式类型修饰符的编译器,有什么可说的吗。
Stroustrup says
“建议只使用属性来控制不影响程序含义但可能有助于检测错误的内容”。如果你能替换所有提到的
|
|
|
3
2
C++03§7.1.5.1p7:
因为在您的示例中,buffer_uu定义为volatile,所以丢弃它是未定义的行为。但是,您可以使用一个适配器来解决这个问题,该适配器将对象定义为非易失性,但会增加易失性:
友谊需要通过已经锁定的对象严格控制非易失性访问:
例子:
这里有两个警告。首先,您仍然可以访问公共数据成员(Something::n),但它们是限定的;这可能会在不同的时候失败。第二,有些东西不知道它是否真的被定义为volatile,如果它被定义为volatile,那么在方法中丢弃volatile(来自“this”或成员)仍然是UB:
主要目标已经实现:对象不必知道它们是以这种方式使用的,并且编译器将阻止对非易失性方法(对于大多数类型都是方法)的调用,除非您显式地通过锁。 |
|
|
4
2
Building on other code 并且完全消除了对volatile说明符的需求,这不仅可以工作,而且可以正确地传播const(类似于迭代器vs const_迭代器)。不幸的是,对于这两种接口类型,它需要相当多的样板代码,但您不必重复任何方法逻辑:每个方法仍然定义一次,即使您必须“复制”“易失性”版本,类似于常量和非常量上方法的正常重载。
将class Something与Alexandrescu使用volatile的要求进行比较:
|
|
|
5
1
从另一个角度来看这个问题。当您将一个变量声明为const时,您告诉编译器该值不能被您的代码更改。但这并不意味着价值 不会 改变例如,如果您这样做:
...根据标准,这会引发未定义的行为,但在实践中会发生一些事情。也许这个值会改变。也许会有一个错误。也许飞行模拟器会发射——谁知道呢。关键是,你不知道在独立于平台的基础上会发生什么。所以
显然的
承诺
既然这是真的,那么
我说不,使用const作为工具来帮助您编写更好的代码并不是对语言的滥用。事实上,我会更进一步,说这是 意图 这一点很重要。 现在,volatile也是如此。将某些内容声明为volatile不会使程序线程安全。它甚至可能不会使变量或对象线程安全。但编译器将强制执行CV限定语义,细心的程序员可以利用这一事实,通过帮助编译器识别可能编写错误的地方,帮助他编写更好的代码。就像编译器在他尝试这样做时帮助他一样:
忘掉内存围栏和易失性对象和变量的原子性,就像你早已忘记的那样
|
|
|
6
0
你最好不要那样做。 不稳定的 甚至不是为了提供线程安全而发明的。它是为了正确地访问内存映射的硬件寄存器而发明的。 不稳定的 关键字对CPU的无序执行功能没有影响。您应该使用适当的操作系统调用或CPU定义的CAS指令、内存围栏等。 |
|
|
7
0
没有读过这篇文章——为什么没有——安德烈说
也就是说,
|
|
|
8
-2
我不知道亚历山德雷斯库的建议是否合理,但尽管我认为他是一个超级聪明的家伙,但他对volatile语义的处理表明,他远远超出了自己的专业领域。Volatile在多线程处理中绝对没有价值(参见 here 为了更好地处理这个问题)所以Alexandrescu的说法 是 对多线程访问很有用,这让我很想知道我能对他的文章的其余部分抱有多大信心。 |
|
|
BenjiFB · C#内存缓存:在一次操作中追加到列表? 1 年前 |
|
SpeakX · 多线程上下文中的弱指针未过期时更新 2 年前 |
|
USMC6072 · 在父事件处理程序中调用异步方法会引发错误 3 年前 |
|
|
Eric · fgets_unlocked()用于多线程读取不同文件 4 年前 |