我必须使用两个线程;一个用于对矩阵进行各种操作,另一个用于监视矩阵运算过程中各个点的虚拟内存。使用全局状态变量'flag'需要此方法。
到目前为止,我有以下内容(为简洁而留下一些内容):
int flag = 0;
int allocate_matrices(int dimension)
{
while (flag == 0) {} //busy wait while main prints memory state
int *matrix = (int *) malloc(sizeof(int)*dimension*dimension);
int *matrix2 = (int *) malloc(sizeof(int)*dimension*dimension);
flag = 0;
while (flag == 0) {} //busy wait while main prints memory state
// more similar actions...
}
int memory_stats()
{
while (flag == 0)
{ system("top"); flag = 1; }
}
int main()
{ //threads are created and joined for these two functions }
正如您所料,system("top")
调用发生一次,矩阵被分配,然后程序陷入无限循环。我觉得这是因为分配给memory_stats
函数的线程已经完成了它的任务,所以flag永远不会再次更新。
这周围有优雅的方式吗?我知道我必须打印四次内存统计数据,所以我觉得我可以在memory_stats
函数中编写四个while循环,并且在每个函数之间的全局标记上等待繁忙,但这似乎很笨拙我。任何帮助或指示将不胜感激。
答案 0 :(得分:5)
您可以使用互斥锁将其锁定。我假设你使用pthread。
pthread_mutex_t mutex;
pthread_mutex_lock(&mutex);
flag=1;
pthread_mutex_unlock (&mutex);
这是关于pthreads,互斥体和其他内容的非常好的教程:https://computing.llnl.gov/tutorials/pthreads/
答案 1 :(得分:5)
挂起的一个可能原因是flag
是一个常规变量,编译器发现它永远不会设置为flag = 0;
和while (flag == 0) {}
之间的非零值或者这个while
位于allocate_matrices()
内。因此它“认为”变量保持为0并且循环变为无限。编译器完全忘记了你的线程。
您可以将flag
定义为volatile
以防止上述情况发生,但在添加volatile
后您可能会遇到其他问题。首先,volatile
不保证变量修改的原子性。
另一个问题是,如果编译器看到an infinite loop that has no side effects, it may be considered undefined behavior and anything could happen, or, at least, not what you're thinking should,还有this。
您需要使用正确的同步原语,如互斥锁。
答案 2 :(得分:0)
您的问题可以通过遵循最新C标准C11的C编译器来解决。 C11有线程和一个名为atomic_flag
的数据类型,它可以基本上用于你的问题中的自旋锁。
答案 3 :(得分:-1)
首先,变量flag
需要声明为volatile
,否则编译器有权在第一个之后省略对它的读取。
有了这个,可以使用一个sequencer / event_counter:一个线程可以在奇数时递增变量,另一个在偶数时递增。由于一个线程总是“拥有”变量,并且使用增量转移所有权,因此没有竞争条件。