我在一本书中遇到了这段代码,这对我来说似乎很奇怪,因为约定是始终释放锁,但是当notify_all()被调用时却不是。
我的问题是,退出块后,是否会从unique_lock调用的锁自动释放? 我知道这是通过使用RAII lock_guard释放的,但这与我无关。
class Logger
{
public:
// Starts a background thread writing log entries to a file.
Logger();
// Prevent copy construction and assignment.
Logger(const Logger& src) = delete;
Logger& operator=(const Logger& rhs) = delete;
// Add log entry to the queue.
void log(const std::string& entry);
// Gracefully shut down background thread.
virtual ~Logger();
private:
// The function running in the background thread.
void processEntries();
// Mutex and condition variable to protect access to the queue.
std::mutex mMutex;
std::condition_variable mCondVar;
std::queue<std::string> mQueue;
// The background thread.
std::thread mThread;
std::atomic<bool> mExit;
// Other members omitted for brevity.
};
Logger::Logger()
{
// Start background thread.
mThread = thread{ &Logger::processEntries, this};
}
void Logger::log(const std::string& entry)
{
// Lock mutex and add entry to the queue.
unique_lock<mutex> lock(mMutex);
mQueue.push(entry);
// Notify condition variable to wake up thread.
mCondVar.Notify_all();
// the lock should be released?
}
void Logger::processEntries()
{
// Open log file.
ofstream ofs("log.txt");
if (ofs.fail()){
cerr << "Failed to open logfile." << endl;
return;
}
// Start processing loop.
unique_lock<mutex> lock(mMutex);
while (true){
// Wait for a notification.
mCondVar.wait(lock)
// Condition variable is notified, so something might be in the queue.
lock.unlock();
// I am pretty sure the moment lock.unlock() is called the other threads will acquire the lock and the instruction will not jump directly to while(true) which kind of defeats the purpose of the application.
// Code continues...
while (true){
lock.lock();
if (mQueue.empty()) {
break;
} else {
ofs << mQueue.front() << endl;
mQueue.pop();
}
lock.unllock();
}
}
}
void logSomeMessages(int id, Logger& logger)
{
for (int =0; i < 10; ++i){
stringstream ss;
ss << "Log entry " << i << " from thread " << id;
logger.log(ss.str());
}
}
int main()
{
Logger logger;
vector<thread> threads;
// Create a few threads all working with the same Logger instance.
for (int i=0; i <10; ++i){
threads.emplace_back(logSomeMessages, i, ref(logger))
}
}