是否有必要在主要结尾处解锁互斥锁?

时间:2016-09-21 22:47:40

标签: c++ pthreads

以下面的代码为例。在pthread_con_wait中,activeMutex被锁定。然后就是" pthread_mutex_unlock(& activeMutex)"必要?因为主要功能很快就会结束。或者,如果我删除该行,则在完成main后,互斥锁将自动解锁。

#include <pthread.h>
#include <iostream>

using namespace std;

int activeThreads = 0;

pthread_mutex_t coutMutex;
pthread_mutex_t activeMutex;
pthread_cond_t  allDoneCondition;

void* Thread(void* v)
{
  unsigned long myId = (unsigned long)v;

  pthread_mutex_lock(&coutMutex);
  cout << "Hello from thread " << myId << endl;
  pthread_mutex_unlock(&coutMutex);
  pthread_mutex_lock(&activeMutex);
  activeThreads--;
  if (activeThreads == 0)
   {
     pthread_cond_signal(&allDoneCondition);
   }
  pthread_mutex_unlock(&activeMutex);
}

int main(int argc, char** argv)
{
  int totalThreads = 8;
  pthread_mutex_init(&coutMutex, 0);
  pthread_mutex_init(&activeMutex, 0);
  pthread_cond_init(&allDoneCondition, 0);

  pthread_mutex_lock(&activeMutex);
  activeThreads = totalThreads;
  for (int i = 0; i < totalThreads; ++i)
    {
      pthread_t t;
      pthread_create(&t, 0, Thread,  (void*)i);
    }
  cout << "Hello from main before exit" << endl;
  pthread_cond_wait(&allDoneCondition, &activeMutex);
  pthread_mutex_unlock(&activeMutex);
}

2 个答案:

答案 0 :(得分:4)

main结束时,操作系统将清除所有程序资源。不释放此互斥锁可能不会产生任何负面后果。真正的问题是,为什么你不释放它?没有释放它就没有好处,你养成了解锁每个锁的好习惯(即良好的资源管理) )。

这是针对您的特定代码的,如果是打开的线程忘记释放互斥锁,则需要更加小心,请参阅here

答案 1 :(得分:1)

这个问题有两个方面:

  1. 当你完成互锁时,你是否应该养成解锁互斥体的良好健康习惯?
  2. 你是否应该浪费你的(希望)宝贵的时间明确地解锁东西?
  3. 这是C ++,所以您可以选择RAII并执行类似于C ++ 11 <thread>标题的操作:

    #include <iostream>
    #include <utility>
    #include <pthread.h>
    
    struct mutex_lock_t {
        pthread_mutex_t* mutex_ { nullptr };
    public:
        mutex_lock_t() = default;
        mutex_lock_t(pthread_mutex_t& mutex) : mutex_(&mutex) { pthread_mutex_lock(mutex_); }
        void unlock()
        {
            if (mutex_) { pthread_mutex_unlock(std::exchange(mutex_, nullptr)); }
        }
        ~mutex_lock_t() noexcept { unlock(); }
    
        mutex_lock_t(const mutex_lock_t&) = delete;
        mutex_lock_t(mutex_lock_t&&) = delete;
        mutex_lock_t operator=(const mutex_lock_t&) = delete;
        mutex_lock_t operator=(mutex_lock_t&&) = delete;
    };
    
    int main()
    {
        pthread_mutex_t mutex {};
        pthread_mutex_init(&mutex, nullptr);
        mutex_lock_t lock(mutex);
        std::cout << "end of main\n";
    }  // auto unlock at end of scope
    

    这里的优点是“我必须”不再是一个问题,你就是这样。

    如果不这样做,那么典型的互斥锁将保存在进程内存中,并且只会在进程终止时与可能访问它的任何内容一起停止存在。

    但是,如果将来您的程序更改并在共享内存中使用互斥锁与其他进程,那么最好依赖RAII清理而不是进行清理。