c++ - 在 cpp 中使用 pthread_mutex_t

标签 c++ locking pthreads mutex

在我的程序中,我有一个守护线程等待任务并将它们打印到文件中。 它的作用是:

void * deamon(void *) {
    while(true) {
        pthread_mutex_lock(manager->getLock());
        while(!manager->isPending()) {
            if (manager->isClosing()) {
                pthread_exit(NULL);
            }
            pthread_cond_wait(manager->getCond(), manager->getLock());
            //check that condition if met - surprises may occur!
        }
                //WRITE TO FILE HERE
        pthread_mutex_unlock(manager->getLock());
    }
    return NULL;
}

因此,正如您所见,当没有待处理任务时,守护进程会等待新任务。 当我得到一个新的时,我将它推送到另一个类中的数据库(守护进程不在一个类中),然后发送一个信号如下:

void Manager::pushNewTask(Task * task) {
    pthread_mutex_lock(_lock);
    map<int,Task *>::iterator it = _tasks->end();
    _tasks->insert(it,make_pair(task->getId(),task));
    // At the first time a signal is sent with no need
    if (_tasks->size() == 1) {
        _pending = true;
        pthread_cond_signal(_cond); //SEND SIGNAL TO DAEMON THREAD
    }
    pthread_mutex_unlock(_lock);
}

三个问题:

  1. 从这里的代码看不清楚,但是 daemon()pushNewTask() 使用相同的 pthread_mutex_t 对象 - 这不是一个问题?当守护进程进入休眠状态(等待)时,它不会解锁互斥量。
  2. 几个函数被同一个pthread_mutex_lock锁定是什么意思?也许只有一个线程可以访问它们中的任何一个?什么时候应该使用不同的 pthread_mutex_t 对象

谢谢

最佳答案

1: Its not clear from the code here but both daemon() and pushNewTask() use the same pthread_mutex_t object - is that not a problem?

pthread_cond_wait(manager->getCond(), manager->getLock());

不,这不是问题。调用 pthread_cond_wait() 释放锁并挂起线程。当条件变量发出信号时。线程重新获取锁,然后从对pthread_cond_wait() 的调用返回。因此,当线程正在运行时,它将拥有锁,而当它处于休眠状态时,锁将被释放(请注意,如果另一个线程持有互斥体上的锁,则该线程无法退出 pthread_cond_wait())。

2: What is the meaning that several functions are locked with the same pthread_mutex_lock? Maybe that only one thread can access either of them? When should I use different pthread_mutex_t objects?

没有。您应该始终使用相同的互斥锁/条件变量对。此外,对对象(在本例中为 Manager 对象)的访问通常由单个锁控制。这意味着只有持有锁的线程才能执行管理器对象中的代码(因此一次只能有一个线程)。在“条件变量”上挂起的线程释放锁,以便其他线程可以在挂起时工作,但必须重新获取锁才能在管理器中执行代码。

更好的用法:

pthread_cond_wait(manager->getCond(), manager->getLock());

这很容易受到竞争条件的影响。应该这样写:

while(<No Tasks available>)
{
    pthread_cond_wait(manager->getCond(), manager->getLock());
}

参见:Thread Wait For Parent

错误:

        if (manager->isClosing()) {
            pthread_exit(NULL);
        }

这是一个问题。线程正在死亡,同时仍然持有互斥体上的锁。在线程死亡之前,它应该释放互斥体。最好通过 RAII 控制互斥量,这样它的使用是异常安全的,并且您可以通过从函数返回而不是调用 pthread_exit() 来退出线程。

使用 pthread_exit() 就像在普通应用程序中调用 exit() 一样。这不是一个好主意,因为堆栈上的自动对象没有被正确销毁。这在 C++ 代码中可能是一个问题,因此不鼓励使用 pthread_exit(),相反,您应该允许线程从启动它的原始函数返回,从而让线程自然死亡。 (PS 不会抛出将线程堆栈展开到末尾的异常。当线程因异常退出时 pthreads 会做什么是未定义的(我见过的大多数系统都会导致应用程序终止)。

关于c++ - 在 cpp 中使用 pthread_mutex_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10486258/

相关文章:

c - 使用 pthread 模拟发送和接收

c++ - Linux C++ : Does a return from main() cause a multithreaded app to terminate?

c# - 通过静态变量从 native 代码访问有状态托管对象

c++ - std::list 的 erase 成员函数是否为所有存储的元素调用析构函数?

c# - 这段代码需要什么样的同步?

winapi - pthread_mutex_lock() 和 EnterCriticalSection

c++ - 是什么导致 move 赋值运算符不被调用?

c++ - Xlib:以最小化或最大化状态创建窗口

sql-server - 在 SQL Server 中强制查询超时

c# - 在多线程环境中使用 Interlocked.Decrement 以及 monitor.wait 和 monitor.pulse 时的错误行为