C处的线程同步

时间:2013-04-09 19:23:29

标签: c multithreading synchronization

我必须使用两个线程;一个用于对矩阵进行各种操作,另一个用于监视矩阵运算过程中各个点的虚拟内存。使用全局状态变量'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循环,并且在每个函数之间的全局标记上等待繁忙,但这似乎很笨拙我。任何帮助或指示将不胜感激。

4 个答案:

答案 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:一个线程可以在奇数时递增变​​量,另一个在偶数时递增。由于一个线程总是“拥有”变量,并且使用增量转移所有权,因此没有竞争条件。