简体   繁体   English

C处的线程同步

[英]Thread Synchronization at C

I have to use two threads; 我必须使用两个线程; one to do various operations on matrices, and the other to monitor virtual memory at various points in the matrix operation process. 一种是对矩阵执行各种操作,另一种是在矩阵操作过程中的各个点监视虚拟内存。 This method is required to use a global state variable 'flag'. 使用全局状态变量“标志”需要此方法。

So far I have the following (leaving some out for brevity): 到目前为止,我有以下内容(为简便起见,省略了一些内容):

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 }

As you might expect, the system("top") call happens once, the the matrices are allocated, then the program falls into an infinite loop. 如您所料, system("top")调用发生一次,分配矩阵,然后程序陷入无限循环。 It seems apparent to me that this is because the thread assigned to the memory_stats function has already completed its duty, so flag will never be updated again. 在我看来,这显然是因为分配给memory_stats函数的线程已经完成其职责,所以标志将永远不会再更新。

Is there an elegant way around this? 有没有解决这个问题的优雅方法? I know I have to print memory stats four times, so it occurs to me that I could write four while loops in the memory_stats function with busy waiting contingent on the global flag in between each of them, but that seems clunky to me. 我知道我必须打印四次内存统计信息,所以我想到我可以在memory_stats函数中编写四个while循环,并根据它们之间的全局标志忙于等待,但这对我来说似乎很笨拙。 Any help or pointers would be appreciated. 任何帮助或指针,将不胜感激。

You can lock it with mutex. 您可以使用互斥锁将其锁定。 I assume you use pthread. 我假设您使用pthread。

pthread_mutex_t mutex;

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

Here is a very good tutorial about pthreads, mutexes and other stuff: https://computing.llnl.gov/tutorials/pthreads/ 这是有关pthread,互斥锁和其他内容的很好的教程: https : //computing.llnl.gov/tutorials/pthreads/

One of the possible reasons for the hang is that flag is a regular variable and the compiler sees that it's never set to a non-zero value between flag = 0; 挂起的可能原因之一是该flag是一个常规变量,并且编译器发现它永远不会在flag = 0;之间设置为非零值flag = 0; and while (flag == 0) {} or in this while inside allocate_matrices() . 并且while (flag == 0) {}或其中while在内部allocate_matrices() And so it "thinks" the variable stays 0 and the loop becomes infinite. 因此,它“认为”变量保持为0,并且循环变为无限。 The compiler is entirely oblivious to your threads. 编译器完全不理会您的线程。

You could define flag as volatile to prevent the above from happening, but you'll likely run into other issues after adding volatile . 您可以将flag定义为volatile以防止发生上述情况,但是添加volatile后,您可能会遇到其他问题。 For one thing, volatile does not guarantee atomicity of variable modifications. 一方面, volatile无法保证变量修改的原子性。

Another issue is that if the compiler sees 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 , also this . 另一个问题是,如果编译器看到一个没有副作用的无限循环,则可以将其视为未定义的行为,并且可能发生任何事情,或者至少不是您想的那样 ,还有this

You need to use proper synchronization primitives like mutexes. 您需要使用适当的同步原语,例如互斥体。

Your problem could be solved with a C compiler that follows the latest C standard, C11. 您的问题可以使用遵循最新C标准C11的C编译器解决。 C11 has threads and a data type called atomic_flag , that can basically used for a spin lock as you have it in your question. C11具有线程和称为atomic_flag的数据类型,基本上可以将其用于自旋锁,因为您有问题。

First of all, the variable flag needs to be declared volatile or else the compiler has license to omit reads to it after the first one. 首先,需要将变量flag声明为volatile ,否则编译器有权在第一个flag之后忽略对其的读取。

With that out of the way, a sequencer/event_counter can be used: one thread may increment the variable when it's odd, the other when it's even. 这样一来,就可以使用sequencer / event_counter:一个线程在奇数时可以递增变量,而另一个在偶数时可以递增变量。 Since one thread always "owns" the variable, and transfers the ownership with the increment, there is no race condition. 由于一个线程始终“拥有”变量,并以增量转移所有权,因此没有竞争条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM