C:线程同步使用pthreads,锁定和解锁互斥



我正在处理一个更大的项目,该项目包括两个线程,其中一个数据库在它们之间共享。一个线程的工作是只倒计时每个活动元素的计时器,当该元素的计时器为零时,它应该将其设置为非活动状态并将其清零。

主线程只是以某种方式操纵活动元素的其他变量。

我不知道如何同步这些线程,尤其是当计时器线程在计时器为零时清理数据库元素时。现在我认为main()while(1)循环中mutex的解锁和锁定之间的时间可能太快了?

如果定时器线程正在等待mutexpthread_mutex_lock()解锁;并且它在main()中解锁,我们知道定时器线程将是下一个锁定mutex的线程吗?或者main()可能太快了,以至于它再次锁定它,因为pthread_mutex_unlock()pthread_mutex_lock()之间没有任务?

我没有使用条件变量的经验,这可能是个好主意吗?

这是我的一个更大项目的一个最小的工作示例。

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <time.h>
#define NUM_COMPUTER 10
typedef struct computer
{
unsigned int active;
unsigned int timer;
int x;
}computer_t;
/**
* Function declarations
*/
void activate(computer_t* comp);
void* timerFunction(void* args);
/**
* Global variables
*/
computer_t database[NUM_COMPUTER];
pthread_mutex_t mutex;

main((函数

/**
* Main
*/
int main(void)
{
memset(database, 0, sizeof database);
// Initialize some database elements
activate(database);
database[0].x = 5;
activate(database + 3);
database[3].x = 23;
activate(database + 9);
database[9].x = -7; 
pthread_t timer_thread;
pthread_create(&timer_thread, NULL, timerFunction, NULL);
while(1)
{
/**
* MAY PROBLEMS OCCUR HERE? UNLOCKING AND LOCKING ALMOST DIRECTLY
*/

// ************* LOCK *************
pthread_mutex_lock(&mutex);
/**
* Manipulate struct members 
*/
for (int i = 0; i < NUM_COMPUTER; i++)
{
if (database[i].active)
{
database[i].x += 1;
}
}
// ************* UNLOCK *************
pthread_mutex_unlock(&mutex);
}
return 0;
}

附加功能

void activate(computer_t* comp)
{
comp->active = 1;
comp->timer = 100;
}
void* timerFunction(void* args)
{
struct timespec ts;
// Sleep interval before checking database again
ts.tv_sec = 1;
ts.tv_nsec = 0;
while(1)
{
// ************* LOCK *************
pthread_mutex_lock(&mutex);
/**
* Go through every database index
*/
for (int index = 0; index < NUM_COMPUTER; index++)
{   
if (database[index].active)
{
if (database[index].timer > 0)
{
database[index].timer--;
}
else
{
/**
* Clean up database index
*/
memset(database + index, 0, sizeof database);
}
}
}
// ************* UNLOCK *************
pthread_mutex_unlock(&mutex);
/**
* Sleep 1 sec before checking database again
*/
nanosleep(&ts, NULL);
}
}

如果计时器线程正在等待mutexpthread_mutex_lock();并且它在main()中解锁,我们知道吗定时器线程将是下一个锁定mutex的线程

否。

至少,不是一般的。这是线程调度策略的问题,您的特定平台可能允许您调整,也可能不允许您调整。pthreads API在这方面没有任何保证。

或者main()太快了,它会再次锁定它,因为两者之间没有任务CCD_ 16和CCD_?

这种情况不仅有可能,而且很可能至少在某些时候发生。

我没有使用条件变量的经验,这可能很好这里的想法?

条件变量是一个重要的工具,但我认为没有理由认为它们在这里会有特别的帮助。

您所呈现的代码的主要问题是,无论何时活动,两个线程都必须锁定整个世界,以便独占使用。因此,即使所有锁定都按要求工作,也不会有真正的并发性,因此多线程增加了复杂性,而没有带来任何实际优势。

如果你想继续这种模式,那么我会放弃多线程,而是设置一个POSIX计时器,以1秒的间隔(或者你喜欢的任何间隔(发出一个标志。然后,单线程程序可以在每个循环迭代的顶部检查该标志,以确定是执行正常工作还是执行一次超时管理。

如果您想要真正的并发性,那么您可能需要缩小由互斥体保护的关键区域,或者从保护所有内容的单个互斥体更改为多个互斥体,每个互斥体都保护所有事物的子集。也许你也可以围绕原子对象和操作而不是互斥体来重新处理事情,但到目前为止我所看到的并没有给我多少信心。