C volatile变量而不是mutex保护变量,用于检查更改的数据
我有一个线程,它基本上可以:C volatile变量而不是mutex保护变量,用于检查更改的数据,c,pthreads,C,Pthreads,我有一个线程,它基本上可以: int changed; //global variable .. for (;;) { pthread_mutex_lock(&mtx); if (changed) { do_changes(); changed = 0; } pthread_mutex_unlock(&mtx); do_stuff(); } 循环每秒运行几十万次,而全局changed变量很少(一天几次)由另一个线程
int changed; //global variable
..
for (;;) {
pthread_mutex_lock(&mtx);
if (changed) {
do_changes();
changed = 0;
}
pthread_mutex_unlock(&mtx);
do_stuff();
}
循环每秒运行几十万次,而全局changed
变量很少(一天几次)由另一个线程设置
换成
volatile int changed; //global variable
..
for (;;) {
if (changed) {
pthread_mutex_lock(&mtx);
do_changes();
changed = 0;
pthread_mutex_unlock(&mtx);
}
do_stuff();
}
我可以用这种方法测量循环3-4%的性能提高,这是值得追求的
然而,不稳定的变数似乎被极力劝阻。
这种方法有什么缺点吗?任何可能导致2。版本是否不能按预期工作?最好将其设置为易失性,以确保编译器不会进行不必要的优化,但不会使其原子化 如果有更多线程正在读取“changed”,则当另一个线程正在等待执行do_changes()时,可能会发生一个线程将“changed”更新为0的情况,这将在释放互斥锁后发生,因为条件已被评估 如果要避免这种情况,请将If语句移动到互斥保护空间内 希望这有帮助
Carles.最好将其设置为易失性,以确保编译器不会进行不必要的优化,但不会使其原子化 如果有更多线程正在读取“changed”,则当另一个线程正在等待执行do_changes()时,可能会发生一个线程将“changed”更新为0的情况,这将在释放互斥锁后发生,因为条件已被评估 如果要避免这种情况,请将If语句移动到互斥保护空间内 希望这有帮助
Carles.最好将其设置为易失性,以确保编译器不会进行不必要的优化,但不会使其原子化 如果有更多线程正在读取“changed”,则当另一个线程正在等待执行do_changes()时,可能会发生一个线程将“changed”更新为0的情况,这将在释放互斥锁后发生,因为条件已被评估 如果要避免这种情况,请将If语句移动到互斥保护空间内 希望这有帮助
Carles.最好将其设置为易失性,以确保编译器不会进行不必要的优化,但不会使其原子化 如果有更多线程正在读取“changed”,则当另一个线程正在等待执行do_changes()时,可能会发生一个线程将“changed”更新为0的情况,这将在释放互斥锁后发生,因为条件已被评估 如果要避免这种情况,请将If语句移动到互斥保护空间内 希望这有帮助
Carles。volatile不会使变量线程安全或原子。你可能喜欢用它 基本上有两个线程在更改变量
changed
从而覆盖以前的值,从而导致数据争用
我不能推荐足够的观看。(它也适用于C)。
volatile
不会使变量线程安全或原子化。你可能喜欢用它
基本上有两个线程在更改变量changed
从而覆盖以前的值,从而导致数据争用
我不能推荐足够的观看。(它也适用于C)。
volatile
不会使变量线程安全或原子化。你可能喜欢用它
基本上有两个线程在更改变量changed
从而覆盖以前的值,从而导致数据争用
我不能推荐足够的观看。(它也适用于C)。
volatile
不会使变量线程安全或原子化。你可能喜欢用它
基本上有两个线程在更改变量changed
从而覆盖以前的值,从而导致数据争用
我不能推荐足够的观看。(它也适用于C)。作者:然而,易变变量似乎被严重劝阻。这种方法有什么缺点吗?任何可能导致2。版本无法按预期工作?
首先:当您尝试使用volatile
时,如果您不需要,请重新考虑。现在看看会发生什么:
1) 如果在多个线程中有循环,则不安全。您可以考虑复制支票:
if (changed) { // quick check
pthread_mutex_lock(&mtx);
if (changed) { // another thread could do the work
...
2) 如果您的代码很关键,您需要使用原子,因为If(changed)
pthread\u mutex\u lock之前的If(changed)
可能由于缓存而看不到它
3) 它可以在具有强内存顺序和原子int访问的x86(_64)上工作,但在其他体系结构上失败。这就是为什么volatile
不受欢迎的原因,请使用原子学(并养成习惯)volatile
不强制原子使用或任何其他同步。原子学do(读修改写指令)
std::原子_标志已验证;
std::互斥体mx;结构MyData{…}数据;
无效更改(){
锁和防护锁(mx);
数据;
已验证。清除();
}
void validate(){
如果(!validated.test_和_set()){
锁和防护锁(mx);
data.update();
}
}
注意:除非您持有锁并使用另一个变量,否则您永远无法确定数据是否有效
4) 只需使用pthread\u spinlock\t尝试您的原始代码即可
5) 小建议:除非你真的知道自己在做什么,否则不要把同步当成上帝。您可以从互斥切换到自旋锁(由其他人编写),并进行一些基准测试
关于编辑和评论:最初的答案只是从1)之前什么都没有开始。事实证明,有些人既没有读完整的问题,也没有读完整的答案。皮蒂是那些情绪低落的选民。这个网站不是facebook,这些投票应该是Either是helpf
std::atomic_flag validated;
std::mutex mx; struct MyData { ... } data;
void change() {
lock_guard<mutex> lock(mx);
data.something();
validated.clear();
}
void validate() {
if(!validated.test_and_set()) {
lock_guard<mutex> lock(mx);
data.update();
}
}