当 std::lock_guard 仍在范围内时,使用 pthread_create 创建线程是不是安全?

Posted

技术标签:

【中文标题】当 std::lock_guard 仍在范围内时,使用 pthread_create 创建线程是不是安全?【英文标题】:Is it safe to create a thread using pthread_create when std::lock_guard is still in scope?当 std::lock_guard 仍在范围内时,使用 pthread_create 创建线程是否安全? 【发布时间】:2019-02-15 12:03:30 【问题描述】:

我有一个类似下面的函数,其中线程通过使用std::lock_guard 互斥锁获取锁并通过ofstream 写入文件。

当当前文件大小增加最大大小时,我想创建一个独立线程来压缩文件并终止。

我想了解当std::lock_guard 仍在范围内时调用pthread_create 的含义。

安全吗?锁是否也会应用于新线程(我不打算这样)?

void log (std::string message)

    std::lock_guard<std::mutex> lck(mtx);

    _outputFile << message << std::endl;
    _outputFile.flush();
    _sequence_number++;
    _curr_file_size = _outputFile.tellp();

    if (_curr_file_size >= max_size) 
        char *lf = strdup(_logfile.c_str());
        // Create an independent thread to compress the file since
        // it takes some time to compress huge files.
        if (!_compress_thread) 
            pthread_create(&_compress_thread, NULL, compress_log, (void *)lf);
        
    


void * compress_log (void *arg) 

    pthread_detach(pthread_self());

    // Code to compress the file
    // ...

    // Create a scope for lock_gaurd

       std::lock_guard<std::mutex> lck(mtx);
       _compress_thread = NULL;
   
   pthread_exit(NULL);

【问题讨论】:

你为什么使用pthread_createstd::mutex 而不是std::thread?顺便说一句,您的比赛条件超过_compress_thread "是否将锁定应用于新线程" 仅当您的代码中有 UB 时。否则保证互斥量一次只能被一个线程锁定。 @Slava,请原谅我的无知,但什么是“UB”?所以新线程不会有这个锁。 UB 是en.cppreference.com/w/cpp/language/ub @Slava,为了解决_compress_thread 上的竞争条件,我更新了上面的代码。你能检查一下并告诉我是否可以吗? 【参考方案1】:

互斥体在线程级别工作,它只影响使用它的线程。当一个线程锁定一个互斥体时,会发生两件事:

    互斥锁已解锁 - 它被锁定,线程继续执行。 互斥锁已被锁定 - 线程不会继续,而是等待互斥锁解锁。

您的新线程运行compress_log() 函数,它根本不访问互斥锁。因此,无论互斥体是否被锁定,它都会运行(您的情况下的互斥体将在log() 退出时解锁)。


一个不相关的建议:使用std::thread 而不是pthread_create,这样您的应用程序变得更便携:

    std::thread [lf]  compress_log(lf);  .detach();

【讨论】:

以上是关于当 std::lock_guard 仍在范围内时,使用 pthread_create 创建线程是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

自动查找已配对的蓝牙设备,当它们在范围内时

linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别

linux C++互斥锁std::lock_guard(轻锁)std::unique_lock(重锁)区别

std::mutex 锁定函数和 std::lock_guard<std::mutex> 的区别?

使用lambda函数进行向量排序,当不在同一范围内时如何传递变量来捕获组?

将 std::lock_guard 与 try_lock 一起使用