跳转至

2. 独占锁

使用下述功能需要包含头文件coke/mutex.h

coke::Mutex

互斥锁用于保护共享数据的独占访问。C++标准库提供了std::mutex互斥锁机制,可用于在多线程访问共享数据时提供保护。在协程环境中,异步操作会在恰当的时候让出线程,让线程可以执行其他协程,这种情况下使用std::mutex会导致死锁等问题。coke::Mutex提供与标准库互斥锁相似的语义,并可以应用在协程中。

在当前协程未锁定互斥锁的情况下执行解锁操作是错误行为,该类不会检测这种行为。

成员函数

  • 构造函数/析构函数

    只可默认构造,不可复制构造,不可移动构造

    Mutex() noexcept;
    
    Mutex(const Mutex &) = delete;
    Mutex &operator= (const Mutex &) = delete;
    
    ~Mutex();
    
  • 尝试锁定

    尝试获得锁但不阻塞,若获取成功则返回true,否则返回false

    bool try_lock();
    
  • 尝试锁定,直到超时

    协程返回一个int类型的整数,coke::TOP_SUCCESS表示获取成功,coke::TOP_TIMEOUT表示因超时而获取失败,coke::TOP_ABORTED表示进程退出,负数表示发生系统错误。可参考全局配置章节的相关内容。

    coke::Task<int> try_lock_for(coke::NanoSec nsec);
    
  • 锁定

    协程返回一个int类型的整数,coke::TOP_SUCCESS表示获取成功,coke::TOP_ABORTED表示进程退出,负数表示发生系统错误。可参考全局配置章节的相关内容。

    coke::Task<int> lock();
    
  • 解锁

    void unlock();
    

示例

#include <iostream>
#include <chrono>

#include "coke/mutex.h"
#include "coke/sleep.h"
#include "coke/wait.h"

using namespace std::chrono_literals;

coke::Task<> worker(coke::Mutex &m) {
    coke::UniqueLock lk(m);

    // 获得锁
    co_await lk.lock();

    std::cout << "locked" << std::endl;
    // 执行需要保护的异步操作,例如写同一个文件
    co_await coke::sleep(100ms);

    std::cout << "finished" << std::endl;
    lk.unlock();

    // 不需要锁的其他操作
}

int main() {
    coke::Mutex m;
    coke::sync_wait(worker(m), worker(m));
    return 0;
}

coke::UniqueLock

coke::UniqueLock是一种通用互斥包装器,支持尝试锁定、锁定、带超时的锁定、以及析构时自动解锁。

template<typename MutexType>
class UniqueLock;

成员函数

  • 构造函数/析构函数

    默认构造时不关联任何互斥锁。使用互斥锁对象构造时,通过参数is_locked来指定该互斥锁是否已经被锁定。该类型可以移动,但不可复制。若析构时当前对象关联互斥锁且处于锁定状态,则自动解锁。

    UniqueLock() noexcept;
    
    explicit UniqueLock(MutexType &m, bool is_locked = false) noexcept;
    
    UniqueLock(UniqueLock &&) noexcept;
    
    ~UniqueLock();
    
  • 检查是否关联互斥锁且处于锁定状态

    bool owns_lock() const noexcept;
    
  • 与另一coke::UniqueLock交换状态

    void swap(UniqueLock &other) noexcept;
    
  • 与互斥锁解除关联,但不解锁它

    MutexType *release() noexcept;
    
  • 尝试锁定

    尝试获得锁但不阻塞,若获取成功则返回true,否则返回false。若互斥锁已经被锁定,抛出以std::errc::resource_deadlock_would_occur为错误码的std::system_error

    bool try_lock();
    
  • 尝试锁定,直到超时

    协程返回一个int类型的整数,coke::TOP_SUCCESS表示获取成功,coke::TOP_TIMEOUT表示因超时而获取失败,coke::TOP_ABORTED表示进程退出,负数表示发生系统错误。可参考全局配置章节的相关内容。若互斥锁已经被锁定,抛出以std::errc::resource_deadlock_would_occur为错误码的std::system_error

    coke::Task<int> try_lock_for(coke::NanoSec nsec);
    
  • 锁定

    协程返回一个int类型的整数,coke::TOP_SUCCESS表示获取成功,coke::TOP_ABORTED表示进程退出,负数表示发生系统错误。可参考全局配置章节的相关内容。若互斥锁已经被锁定,抛出以std::errc::resource_deadlock_would_occur为错误码的std::system_error

    coke::Task<int> lock();
    
  • 解锁

    若当前对象未关联互斥锁,或者未处于锁定状态,抛出以std::errc::operation_not_permitted为错误码的std::system_error

    void unlock();