-
总览
-
核心
-
const 修饰的成员函数理论上说是不会修改值的. -
如果有成员mutable ,则是可以修改. -
修改就会遇到资源竞争和多线程安全问题。
-
多线程安全
-
只有多线程共享的数据才会有多线程安全问题。 -
即一致性问题,其实对于某些数据,只有整个独占才能保证多线程安全。 -
或者确认不共享,只有一个线程串行使用。
-
文章内容
-
多线程安全函数的案例不太靠谱。 -
不过是针对C++98 和C++11 来将,还是有一点内容的。
-
多线程安全
-
读写模式
-
采用volatile 和内存屏障的形式保证一致性. -
修改方用函数修改了之后就写屏障使生效。读取方则短暂用读屏障,保证数据有效。 -
适合特别短的代码等待。长等待需要用锁,让线程睡眠,以让出资源,而不是空转。 -
volatile 和barrier 一般是在C 语言里面使用.
-
统计模式
-
atomic 类对基本类型实现原子操作. 效率没有上面的高,不过更安全可靠.
-
长任务模式
-
对于与需要常事件处理并占用一系列资源的情况. 需要用互斥。 -
mutex,sem,condition 等.
-
C++11
-
简介
-
支持了函数声明为const ,表示函数不会修改类的成员数据,const 类型. -
这类修饰表明了不会在函数中修改,不保证其他不会修改. -
仅仅是限制自身不会对内容进行修改.
-
修饰目的
-
用于多线程安全,虽然可能也会发生修改. -
但是语义上不能修改. 而自己开发的时候 也需要注意. -
虽然 也可以通过mutable 修饰变量可修改.
-
const 函数的本质
-
普通函数,第一个参数是变量指针,第二三参数是其他. -
函数只能保障自己不会修改输入数据,即obj 对象.
-
发现问题
-
编译阶段发现问题。 -
可以较早发现这类错误做法。 -
主要是不修改当前类的值。
-
案例
class T {
public:
void cool() const {
x = 1;
}
public:
mutable int x{0};
};
int main() {
T d;
d.cool();
}
-
这类是可以的,但是修改了值,就存在竞争问题。 -
只读一般就不存在资源竞争问题。
-
竞争的原因
-
CPU 缓存一致性导致读写数据不对。 -
不修改,只读就不存在问题。对共享数据改就存在问题。
-
总结
-
建议const 尽量做到多线程安全,即不修改数据. -
std::atomic 比mutex 效率高,使用场景是单个标量或者某个内存区间的值.
|