死锁和/或在线程死机之前返回

deadlock andor return before thread is dead

本文关键字:死机 返回 线程 死锁      更新时间:2023-10-16

我在同样的情况下被困了大约 2 天,我真的很感激任何帮助。主线程正在调用 initDevice() 函数,该函数正在打开文件并创建一个新线程,他将成为具有 writeToDeviceHandler() 函数的"写入"线程。write2device()是从main()调用的,应该插入新任务以写入(将来)到map<int,Task*>。问题是,有时应用程序会卡在某种无限循环或死锁上,有时它会写入<(#个任务)来写入。任何人都可以看到代码中是否有任何问题吗?谢谢!

int write2device(char *buffer, int length)
{
    if(is_running)
    {
        pthread_mutex_lock(&tasks_mutex);//LOCK
        int curr_id = getNextAvailableId();
        Task* new_task = new Task(buffer,length, curr_id);
        tasks[curr_id] = new_task;
        pthread_cond_signal(&tasks_cv);
        given_ids.insert(curr_id);
        pthread_mutex_unlock(&tasks_mutex);//UNLOCK
        return curr_id;
    }
    return FAIL;
}
int initdevice(char *filename)
{
    is_running = true;
    pthread_cond_signal(&tasks_cv);
    output_file.open(filename);
    if(!output_file.is_open())
    {
        cerr << "Error opening file" << endl;
        is_running = false;
        return SYSTEM_ERROR;
    }
    int res = pthread_create(&writing_thread, NULL, writeToDeviceHandler, NULL);//Create the writing to file thread.
    if(res != 0)
    {
        cerr <<  "Error creating the writing thread" <<endl;
        exit(FAIL);
    }
    return SUCCESS;
}
void *writeToDeviceHandler(void *arg)
{
    Task* curr_task;
    while(is_running)
    {
        pthread_mutex_lock(&tasks_mutex);
        cout << "IN LOOP - size of db: " << tasks.size() << endl;
        if(tasks.empty())
        {
            pthread_cond_wait(&tasks_cv, &tasks_mutex);
        }
        if(tasks.empty()) cout << "Empty, still finding thread" <<endl;
        curr_task = tasks.begin()->second;
        if(curr_task == NULL)
        {
            pthread_mutex_unlock(&tasks_mutex);
            continue;
        }
        //copy from tasks to file
        output_file.write(curr_task->getBuff(), curr_task->getLength());
        ids.remove(curr_task->getId());
        tasks.erase(curr_task->getId());
        delete curr_task;
        pthread_mutex_unlock(&tasks_mutex);
    }
    pthread_exit(NULL);
    return NULL;
}

您的代码不正确,因为它没有围绕pthread_cond_wait调用的循环。pthread_cond_wait调用可能会在虚假唤醒时返回。您必须在它返回后检查您的唤醒状况。在您的情况下,它看起来像这样:

while (task.empty ())
  pthread_cond_wait(&tasks_cv, &tasks_mutex);

您的代码也缺少错误检查。请检查所有函数的所有返回值是否存在错误。

您的writeToDeviceHandler代码在持有互斥锁的同时完成所有工作,完全违背了线程的意义。如果另一个线程想要给这个线程工作,它将不得不获取tasks_mutex。为此,它必须完成,直到此线程完成写入并释放互斥锁。那么为什么要打扰这个线程呢?

当您有一个保护需要完成的工作的互斥锁时,重点是实际使用释放的互斥锁来执行工作。这样,其他线程就不必等待您完成工作。