Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 互斥线程-代码似乎没有正确退出_C_Multithreading_Mutex - Fatal编程技术网

C 互斥线程-代码似乎没有正确退出

C 互斥线程-代码似乎没有正确退出,c,multithreading,mutex,C,Multithreading,Mutex,我这里有两种线程的代码。一种产生数据,另一种消耗数据。任何时候都只能存在一定数量的数据,因此一旦创建了一定数量的数据,即当sharedData=BUFFER时,生产者将暂停生产,当sharedData=0时,消费者将暂停生产。也只有这么多的数据可以存储在dataleft中,一旦所有的数据都被创建和使用,程序应该结束 出于某种原因,我在代码末尾的printf行似乎从未触发过。因为这个原因,我无法判断线程是否正确关闭。我觉得我做了一些非常愚蠢的事情,但我看不出问题所在 一开始有几个定义: #defi

我这里有两种线程的代码。一种产生数据,另一种消耗数据。任何时候都只能存在一定数量的数据,因此一旦创建了一定数量的数据,即当sharedData=BUFFER时,生产者将暂停生产,当sharedData=0时,消费者将暂停生产。也只有这么多的数据可以存储在dataleft中,一旦所有的数据都被创建和使用,程序应该结束

出于某种原因,我在代码末尾的printf行似乎从未触发过。因为这个原因,我无法判断线程是否正确关闭。我觉得我做了一些非常愚蠢的事情,但我看不出问题所在

一开始有几个定义:

#define                 NUMCONSUMERS    4
#define                 NUMPRODUCERS    4
#define                 PACKETS         10
#define                 tryMainlock     pthread_mutex_trylock(&dataMutex)
#define                 openMainlock    pthread_mutex_lock(&dataMutex)
#define                 closeMainlock   pthread_mutex_unlock(&dataMutex)
#define                 waitMainlock    pthread_cond_wait(&dataPresentCondition, &dataMutex);
#define                 signalMainlock  pthread_cond_signal(&dataPresentCondition);

#define                 trydatalock     pthread_mutex_trylock(&IsthereDataleft)
#define                 opendatalock    pthread_mutex_lock(&IsthereDataleft)
#define                 closedatalock   pthread_mutex_unlock(&IsthereDataleft)

pthread_mutex_t         dataMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t          dataPresentCondition = PTHREAD_COND_INITIALIZER;

pthread_mutex_t         IsthereDataleft = PTHREAD_MUTEX_INITIALIZER;

int                     sharedData=0;   //amount of data present
int                     BUFFER = 5;
int                     dataleft=PACKETS;
主要功能:

int main(int argc, char **argv)
{
int rc;                                 
int i;
pthread_t  consumer[NUMCONSUMERS];
pthread_t  producer[NUMPRODUCERS];

rc = opendatalock;                      //lock to determine whether there's any point waiting for data

for (i=0; i <NUMPRODUCERS; i++) {       //Build up the producers
    rc = pthread_create(&producer[i], NULL, Producer, (void *)i);
    if (rc)
        printf("Error building Producer Thread: %x\n", i);
}

for (i=0; i <NUMCONSUMERS; i++) {       //Build up the consumers
    rc = pthread_create(&consumer[i], NULL, Consumer, (void *)i);
    if (rc)
        printf("Error building Consumer Thread: %x\n", i);
}

printf("All Producers and Consumers created\n");

for (i=0; i <NUMPRODUCERS; i++) {       //Join up the producers
    rc = pthread_join(producer[i], NULL);
    if (rc)
        printf("Error: Producer %x: Failed to join\n", i);
}

rc = closedatalock;                     //producers finished, no data left to make

printf("datalock closed, consumers finishing...\n");
for (i=0; i <NUMCONSUMERS; i++) {       //Join up the consumers
    rc = pthread_join(consumer[i], NULL);
    if (rc)
        printf("Error: Consumer %x: Failed to join\n", i);
}
rc = pthread_mutex_destroy(&dataMutex);
rc = pthread_cond_destroy(&dataPresentCondition);
rc = pthread_mutex_destroy(&IsthereDataleft);

printf("All Threads finished. Exiting....\n");
return 0;
}
和生产者线程:

void *Consumer(void *threadid){
int rc;
printf("Consumer Thread %x: Created\n", (int)threadid);
while (1)
{
    printf("Consumer %x: Entering Loop\n", (int)threadid);
    rc = openMainlock;      //take hold of main lock
    if (rc)
    {
        printf("Consumer %x: Waiting...\n", (int)threadid);
        rc = waitMainlock;  //if main lock is taken, wait
        if (rc)             //if wait fails, exit the thread.
        {
            printf("Consumer Thread %x: wait for Main Lock failed\n", threadid);
            exit(0);
        }
    }

    while (sharedData == 0) //if the buffer is empty
    {
        rc = trydatalock;
        if (!rc)
        {
            printf("Consumer %x: Completed. Exiting...\n");
            exit(0);
        }
        rc = closeMainlock;
        if (rc)
        {
            printf("code.\n");
        }
        rc = waitMainlock;
        if (rc)
        {
            printf("code.\n");
        }
    }
    sharedData--;
    rc = closeMainlock;
    rc = signalMainlock;
    if (rc)
        {
            printf("code.\n");
        }
    printf("Consumer %x: Releasing Lock\n", (int)threadid);         
}
}
void *Producer(void *threadid){
int rc;
printf("Producer Thread %x: Created\n", (int)threadid);
while (1)
{
    printf("Producer %x: Entering Loop\n", (int)threadid);
    rc = openMainlock;          //take hold of the lock
    if (rc)                     //if lock is currently being used by a consumer or a producer
    {   
        printf("Producer %x: Waiting...\n", (int)threadid);
        rc = waitMainlock;      //wait here until lock is released
        if (rc)
        {
            printf("Producer Thread %x: wait for Main Lock failed\n", threadid);
            exit(0);
        }
    }
    if (!dataleft)              //If there's no data left to add to the stream, close the thread
    {
        printf("Producer Thread %x: Completed, exiting...\n", (int)threadid);
        exit(0);
    }
    while (sharedData >=BUFFER)
    {
        rc = closeMainlock;
        if (rc)
        {
            printf("code.\n");
        }
        rc = waitMainlock;
        if (rc)
        {
            printf("code.\n");
        }
    }
    printf("Producer %x: Lock Acquired\n", (int)threadid);
    sharedData++;
    dataleft--;
    rc = closeMainlock;
    rc = signalMainlock;
    if (rc)
        {
            printf("code.\n");
        }
    printf("Producer %x: Releasing Lock\n", (int)threadid);
}
}

openMainlock的使用似乎有点问题,它扩展为pthread\u mutex\u lock调用

一方面,您不应该期望从openMainlock获得非零返回值:pthread_mutex_lock应该返回已获取的零锁或块,除非互斥体未初始化或是错误检查互斥体


此外,一旦获得锁,如果生产者完成,即dataleft为零,线程将调用exit0,这将终止整个进程,而不是终止线程。应该改用pthread_exit,或者只从函数返回,但请注意,此时您仍然拥有主锁,不会释放主锁。

查看这段代码:

    if (!rc)
    {
        printf("Consumer %x: Completed. Exiting...\n");
        exit(0);
    }
如果消费者已完成,则流程!终止。您需要改用pthread_exit,或者直接从thread函数返回

那么还有

../nptl/pthread_mutex_lock.c:80:
    __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
我运行了几次代码。这可能是由双重解锁或其他无效使用引起的。我首先要清理这些奇怪的宏,这样你就可以自由地查看程序本身的逻辑

另外,关于互斥体的一个重要建议是:始终准确地记录哪些数据应该受到互斥体的保护。关键是它并不总是清晰的,如果出现错误,则意味着您在没有同步的情况下意外地访问了数据。为了明确这一点,请使用如下结构:

 struct {
     pthread_mutex_t mutex;
     pthread_cond_t cond;
     int data;
 } synced_data = {
     PTHREAD_MUTEX_INITIALIZER,
     PTHREAD_COND_INITIALIZER,
     0
 };

实际上,文档的重要性不仅仅在于共享数据。例如,iStReDATAlFET:这是互斥体,但它不能保护任何东西,对吧?相反,它用于向已启动的线程发出信号,表示已无事可做,对吗?记录这一点不仅有助于其他人理解您的代码,而且可以确保您了解自己的意图。有时,当你试图解释它时,你会发现有些东西是没有意义的。

你会用一个简单的int作为互斥吗?这行不通,请检查pthread_互斥体。。。功能。还有,什么是waitMainlock和closeMainlock?你的代码里没有这些,除非我遗漏了什么。哦,等等,该死的。我在开始时定义了一些位,我将把它们添加进去。互斥函数返回一个int。当函数正确执行时,它返回0,即,它接受lock.Ouch。这些宏具有很强的误导性。如果您使用所有的大写字母,那么至少很明显这些都是宏。也就是说,如果要避免键入这些函数调用,请使用锁定互斥体的子例程,检查returnvalue并在失败时退出。这样,主要功能就不会被错误处理弄得乱七八糟。