【发布时间】:2019-02-18 15:22:57
【问题描述】:
我有一个类似下面的函数,其中线程通过使用 std::lock_guard 互斥锁获取锁并通过 ofstream 写入文件。
当当前文件大小增加最大大小时,我创建一个独立线程来压缩文件并终止。
如果日志文件很大(比如 ~500MB),压缩大约需要 25 秒以上。 我分离了压缩线程,因为没有其他线程(或主线程)想要等待这个线程完成。
但我需要知道压缩线程在执行以下行之前没有运行:
_compress_thread(compress_log, _logfile).detach();
示例代码sn-p:
void log (std::string message)
{
// Lock using mutex
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) {
// Code to close the file stream, rename the file, and reopen
...
// Create an independent thread to compress the file since
// it takes some time to compress huge files.
if (the_compress_thread_is_not_already_running) //pseudo code
{
_compress_thread(compress_log, _logfile).detach();
}
}
}
在上述if 条件下,即the_compress_thread_is_not_already_running,如何确定压缩线程没有运行?
void * compress_log (std::string s)
{
// Compress the file
// ...
}
【问题讨论】:
-
如果您需要知道线程是否仍在运行,那么听起来您并不真正想要
detach。detach通常表示设计存在问题。语句“我需要知道压缩线程没有运行”意味着应该有1个压缩线程,这与使用detach相反,并且与语句“没有其他线程”相反(或主)想要等待这个线程完成”. -
您也可以使用
std::async并保留一个未来的对象。然后你可以使用它来确保在你再次调用之前之前的调用已经结束。 -
为什么会有问题?
-
std::thread _compress_thread(compress_log, _logfile);是一个局部变量,对您的函数来说是局部变量,并且总是创建一个新对象。它从不引用现有线程。 -
@C_user5 然后
detach与您想要做的完全相反。join在您为其分配新值之前使用它。detach的意思是“我不关心这个线程,它什么时候完成,或者即使它完成”,这在你的情况下是不正确的。编辑:但是正如 cmets 和答案所指出的那样,最好使用std::async并存储std::future来代替。std::thread旨在用作低级基本对象。它的设计不是为了易于使用。如果您想异步运行任务(压缩文件),请使用std::async。这就是它的用途。
标签: c++ multithreading stdthread