2

我必须使用两个线程;一是对矩阵进行各种运算,二是监控矩阵运算过程中各个点的虚拟内存。此方法需要使用全局状态变量“标志”。

到目前为止,我有以下内容(为简洁起见,省略了一些):

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函数的线程已经完成了它的职责,所以标志将永远不会再次更新。

有没有一种优雅的方式来解决这个问题?我知道我必须打印四次内存统计信息,所以我突然想到我可以在memory_stats函数中编写四个 while 循环,忙于等待它们之间的全局标志,但这对我来说似乎很笨拙。任何帮助或指示将不胜感激。

4

4 回答 4

6

您可以使用互斥锁锁定它。我假设您使用 pthread。

pthread_mutex_t mutex;

pthread_mutex_lock(&mutex);
flag=1;
pthread_mutex_unlock (&mutex);

这是一个关于 pthread、互斥锁和其他东西的非常好的教程:https ://computing.llnl.gov/tutorials/pthreads/

于 2013-04-09T19:31:06.557 回答
6

挂起的可能原因之一是它是一个常规变量,编译器发现它从未设置为介于and或 in this insideflag之间的非零值。因此它“认为”变量保持为 0 并且循环变为无限。编译器完全没有注意到您的线程。flag = 0;while (flag == 0) {}whileallocate_matrices()

您可以定义flagvolatile以防止上述情况发生,但添加后可能会遇到其他问题volatile。一方面,volatile不保证变量修改的原子性。

另一个问题是,如果编译器看到一个没有副作用的无限循环,它可能被认为是未定义的行为,并且任何事情都可能发生,或者至少不是你想的应该的,还有this

您需要使用适当的同步原语,如互斥锁。

于 2013-04-09T19:51:25.310 回答
0

您的问题可以使用遵循最新 C 标准 C11 的 C 编译器来解决。C11 具有线程和称为 的数据类型atomic_flag,基本上可以用于自旋锁,就像您在问题中所使用的那样。

于 2013-04-09T20:52:32.603 回答
-1

首先,flag需要声明变量,volatile否则编译器有权在第一个变量之后省略对其的读取。

这样一来,就可以使用 sequencer/event_counter 了:一个线程可以在变量为奇数时递增,而另一个线程在变量为偶数时递增。由于一个线程始终“拥有”该变量,并随着增量转移所有权,因此不存在竞争条件。

于 2013-04-09T19:43:00.923 回答