use*_*166 5 c concurrency multithreading multicore
关于C语言中的并发编程,我有一个相当具体的问题.我已经对此进行了相当多的研究,但已经看到了几个相互矛盾的答案,所以我希望得到一些澄清.我有一个程序,如下所示(对于冗长的代码块抱歉):
typedef struct {
pthread_mutex_t mutex;
/* some shared data */
int eventCounter;
} SharedData;
SharedData globalSharedData;
typedef struct {
/* details unimportant */
} NewData;
void newData(NewData data) {
int localCopyOfCounter;
if (/* information contained in new data triggers an
event */) {
pthread_mutex_lock(&globalSharedData.mutex);
localCopyOfCounter = ++globalSharedData.eventCounter;
pthread_mutex_unlock(&globalSharedData.mutex);
}
else {
return;
}
/* Perform long running computation. */
if (localCopyOfCounter != globalSharedData.eventCounter) {
/* A new event has happened, old information is stale and
the current computation can be aborted. */
return;
}
/* Perform another long running computation whose results
depend on the previous one. */
if (localCopyOfCounter != globalSharedData.eventCounter) {
/* Another check for new event that causes information
to be stale. */
return;
}
/* Final stage of computation whose results depend on two
previous stages. */
}
Run Code Online (Sandbox Code Playgroud)
有一个线程池为传入数据的连接提供服务,因此可以同时运行多个newData实例.在多处理器环境中,我知道在使代码处理部分代码正确时有两个问题:阻止编译器在寄存器中缓存共享计数器副本,以便其他线程无法看到它,并强制执行CPU以及时的方式将计数器值的存储写入内存,以便其他线程可以看到它.我宁愿不在计数器检查周围使用同步调用,因为部分读取计数器值是可接受的(它将产生一个不同于本地副本的值,这应该足以断定事件已经发生).将SharedData中的eventCounter字段声明为volatile是否足够,或者我是否需要在此处执行其他操作?还有更好的方法来处理这个问题吗?
不幸的是,C 标准对并发性的描述很少。然而,大多数编译器(无论如何,gcc 和 msvc)都会将 易失性读取视为具有获取语义- 易失性变量将在每次访问时从内存中重新加载。这是可取的,您现在的代码可能最终会比较寄存器中缓存的值。如果这两个比较都得到优化,我什至不会感到惊讶。
所以答案是肯定的,让其eventCounter
变得易失。或者,如果您不想过多限制编译器,可以使用以下函数来执行eventCounter
.
int load_acquire(volatile int * counter) { return *counter; }
if (localCopy != load_acquire(&sharedCopy))
// ...
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1217 次 |
最近记录: |