与普通互斥锁相比,独特锁如何工作?

时间:2015-08-21 08:08:56

标签: c++ c++11 visual-c++

我遇到了book提供的代码示例。顺便说一句这本书有不好的评论。我很遗憾我买了它

std::mutex m_mutex;
mutable std::unique_lock<std::mutex> m_finishedQueryLock{ m_mutex, std::defer_lock };

bool m_playerQuit{ false };
void SetPlayerQuit()
{
    m_finishedQueryLock.lock();
    m_playerQuit = true;
    m_finishedQueryLock.unlock();
}

我不满意这本书对它是如何工作的解释以及我为什么要使用它。我已经知道互斥锁如何工作及其实现,但我很难理解上面代码的第二行。为什么它有一个可变的关键字呢?

我是C ++编程的新手。因此,基本的解释水平对我有很大的帮助。

3 个答案:

答案 0 :(得分:8)

这个例子看起来很愚蠢。

第二行是声明非静态数据成员,

  • 该成员为mutable(由于以下原因);
  • 该成员是std::unique_lock<std::mutex>类型的对象,它是用于锁定/解锁关联的互斥对象的帮助程序类型;
  • 在创建类的实例时,通过调用其构造函数并传递m_mutex和特殊标记std::defer_lock作为参数来初始化成员。

但这样做是愚蠢的,如果有这样的例子,那本书就有不好评论我并不感到惊讶。

unique_lock的要点是锁定关联的互斥锁,然后在超出范围时自动解锁。像这样创建一个unique_lock成员是愚蠢的,因为它不会超出函数末尾的范围,因此代码绝对没有优势:

mutable std::mutex m_mutex;

bool m_playerQuit{ false };

void SetPlayerQuit()
{
    m_mutex.lock();
    m_playerQuit = true;
    m_mutex.unlock();
}

但是这个手动解锁具有unique_lock旨在解决的所有问题,因此它应该使用范围锁(unique_locklock_guard)但仅在函数范围内,而不是成员:

mutable std::mutex m_mutex;

bool m_playerQuit{ false };

void SetPlayerQuit()
{
    std::lock_guard<std::mutex> lock(m_mutex);
    m_playerQuit = true;
}   // m_mutex is automatically unlocked by the ~lock_guard destructor

mutable关键字是必需的,以便您可以锁定const成员函数中的互斥锁。锁定和解锁互斥锁是一种修改互斥锁的非const操作,如果它不可变,则不允许在const成员中使用。

答案 1 :(得分:1)

unique_lockRAII系统。创建时,以mutex为参数,它将锁定互斥锁,当离开范围时,它将被销毁,从而解锁互斥锁。当您需要提前解锁时,可以像示例中一样调用unlock()函数。

使用示例中的unique_lock并不会直接使用互斥锁创建附加值。

答案 2 :(得分:0)

所有答案都很好地解释了为什么这个例子并不好。如果您想使用from http.server import BaseHTTPRequestHandler, HTTPServer import urllib.parse class oraHTTPRequestHandler(BaseHTTPRequestHandler): def methodA(self): self.send_response(200) self.end_headers() self.wfile.write('methodA'.encode('utf-8')) return def methodB(self): self.send_response(200) self.end_headers() self.wfile.write('methodB'.encode('utf-8')) return def do_GET(self): parsed_path = urllib.parse.urlparse(self.path) if parsed_path.path.endswith('/methodA'): self.methodA() elif parsed_path.path.endswith('/methodB'): self.methodB() else: self.send_error(501) return def run(): print('http server is starting...') server_address = ('127.0.0.1', 8080) httpd = HTTPServer(server_address, oraHTTPRequestHandler) print('http server is running...') httpd.serve_forever() if __name__ == '__main__': run() 代替std::unique_lock,我会回答。

当线程正在等待某事时,可以使用std::lock_guard。条件变量使用延迟锁定,因此使用std::condition_variable,允许延迟锁定。我不认为您明确需要说您需要延迟锁定,如示例中所示。

要掌握这些概念,首先需要了解RAII是什么。然后看看this reference。可以找到条件变量的示例here

相关问题