福建联泰建设集团网站,诚讯网站设计,网站优化的代码,交易网站建设具体方案阅读导航 引言一、RAII机制1. 概念2. 原理3. 优点 二、Lock_guard1. 官方文档2. 概念3. 底层类模版4. 使用示例 三、Unique_lock1. 官方文档2. 概念及底层3. 使用示例 四、总结温馨提示 引言
在C11标准中#xff0c;为了更方便地使用互斥锁#xff08;Mutex#xff09;来保… 阅读导航 引言一、RAII机制1. 概念2. 原理3. 优点 二、Lock_guard1. 官方文档2. 概念3. 底层类模版4. 使用示例 三、Unique_lock1. 官方文档2. 概念及底层3. 使用示例 四、总结温馨提示 引言
在C11标准中为了更方便地使用互斥锁Mutex来保证多线程程序的安全性Lock_guard和Unique_lock这两个类也被引入。它们作为RAII资源获取即初始化机制的一种实现方式在多线程编程中起到了重要的作用。Lock_guard和Unique_lock可以帮助程序员自动管理互斥锁的加锁和解锁避免忘记解锁而导致的死锁等问题。本文将详细介绍Lock_guard和Unique_lock的使用方法和区别并通过实例展示如何使用它们来实现线程安全的程序。
一、RAII机制
1. 概念
RAIIResource Acquisition Is Initialization是一种C编程技术它通过将资源的获取和释放与对象的生命周期绑定在一起以确保资源在对象创建时获取在对象销毁时释放。这种技术利用了C对象的构造函数和析构函数的调用机制使得资源的管理变得更加简洁、安全和可靠。
2. 原理
使用RAII的关键在于将资源的获取和释放操作分别放置在对象的构造函数和析构函数中。当对象被创建时构造函数负责获取资源并进行必要的初始化工作当对象被销毁时析构函数负责释放资源并进行清理工作。由于C保证在对象销毁时析构函数会被自动调用所以资源的释放也就得到了保证。
3. 优点
RAII技术的优点如下
简洁性通过对象的自动构造和析构减少了手动管理资源的代码量使得程序更加简洁易读。安全性确保资源在适当的时候被释放避免了常见的资源泄漏和错误状态的产生。可靠性无论在何时何地发生异常或提前退出都能够保证资源的正确释放提高程序的可靠性。可扩展性通过继承和组合等方式可以方便地扩展和管理更复杂的资源。
常见的使用RAII技术的例子包括使用智能指针管理动态内存、使用文件对象进行文件操作、使用互斥锁类进行线程同步等。通过合理运用RAII技术可以有效地提高代码的可维护性、可读性和可靠性是现代C编程中的重要技术之一。
二、Lock_guard
1. 官方文档
⭕Lock_guard官方文档 2. 概念
std::lock_guard是C标准库中的一个RAII类模板用于管理互斥锁std::mutex的加锁和解锁操作。它提供了一种简单且安全的方式来确保在退出作用域时互斥锁会被正确地释放从而避免了忘记解锁而导致的死锁和资源泄漏等问题。
3. 底层类模版
// lock_guard类模板用于管理互斥锁的加锁和解锁操作
templateclass _Mutex
class lock_guard
{
public:// 构造函数在创建lock_guard对象时自动上锁互斥锁_Mtxexplicit lock_guard(_Mutex _Mtx): _MyMutex(_Mtx){_MyMutex.lock(); // 使用互斥锁的lock()成员函数进行上锁操作}// 构造函数在已经上锁的情况下创建lock_guard对象// 在这种情况下不需要再次上锁互斥锁因此该构造函数空实现lock_guard(_Mutex _Mtx, adopt_lock_t): _MyMutex(_Mtx){}// 析构函数在lock_guard对象销毁时自动解锁互斥锁_Mtx// 使用互斥锁的unlock()成员函数进行解锁操作~lock_guard() _NOEXCEPT{_MyMutex.unlock();}// 禁用拷贝构造函数和拷贝赋值运算符确保lock_guard对象不可拷贝lock_guard(const lock_guard) delete;lock_guard operator(const lock_guard) delete;private:_Mutex _MyMutex; // 引用类型成员变量用于保存互斥锁的引用
};
lock_guard类有以下几个重要成员函数
explicit lock_guard(_Mutex _Mtx)该构造函数会在创建lock_guard对象时自动上锁互斥锁_Mtx。它使用互斥锁的lock()成员函数进行上锁操作。lock_guard(_Mutex _Mtx, adopt_lock_t)该构造函数用于在已经上锁的情况下创建lock_guard对象。在这种情况下不需要再次上锁互斥锁因此该构造函数空实现。~lock_guard() _NOEXCEPT析构函数会在lock_guard对象销毁时自动解锁互斥锁_Mtx。它使用互斥锁的unlock()成员函数进行解锁操作。lock_guard(const lock_guard) delete和lock_guard operator(const lock_guard) delete禁用拷贝构造函数和拷贝赋值运算符确保lock_guard对象不可拷贝。
注意lock_guard禁用了拷贝构造函数和拷贝赋值运算符意味着它不支持拷贝语义只能通过直接创建对象来使用。这样可以避免多个lock_guard对象同时管理同一个互斥锁而导致的错误行为。
4. 使用示例
使用std::lock_guard非常简单只需在需要加锁的代码块的开始处创建一个std::lock_guard对象并将互斥锁作为参数传递给它的构造函数。当代码块结束时std::lock_guard对象的析构函数会自动调用从而触发互斥锁的解锁操作。
下面是一个示例代码展示了如何使用std::lock_guard来管理互斥锁的加锁和解锁
#include iostream
#include thread
#include mutexstd::mutex mtx; // 定义一个互斥锁void printMessage(const std::string message) {std::lock_guardstd::mutex lock(mtx); // 创建std::lock_guard对象并传入互斥锁for (int i 0; i 5; i) {std::cout message std::endl;}
}int main() {std::thread t1(printMessage, Hello);std::thread t2(printMessage, World);t1.join();t2.join();return 0;
}在上述示例中printMessage函数通过创建一个std::lock_guard对象lock来确保在执行打印操作之前获得互斥锁并在函数返回时自动释放互斥锁。这样当多个线程调用printMessage函数时它们之间的执行将会排他性地进行避免了数据竞争和输出混乱的问题。
总之std::lock_guard提供了一种简单且安全的方式来管理互斥锁的加锁和解锁操作帮助我们在使用互斥锁时避免常见的错误并提高代码的可靠性和可维护性。
三、Unique_lock
1. 官方文档
⭕Unique_lock官方文档 2. 概念及底层
unique_lock类模板与lock_guard类似都是以资源获取就是初始化Resource Acquisition Is Initialization缩写为RAII的方式对锁进行封装。它们都采用了独占所有权的机制即不能进行拷贝操作。在构造或移动赋值时需要将一个Mutex对象作为参数传递给unique_lock对象新创建的unique_lock对象会负责管理该Mutex对象的上锁和解锁操作。
对于使用unique_lock实例化的对象当对象被创建时会自动调用构造函数对Mutex对象进行上锁操作确保当前线程获得互斥访问权限。而当unique_lock对象销毁时会自动调用析构函数解锁Mutex对象释放互斥访问权限。通过这种方式可以方便地避免死锁问题的发生保证线程安全性。
与lock_guard不同的是unique_lock更加的灵活提供了更多的成员函数
上锁/解锁操作lock、try_lock、try_lock_for、try_lock_until和unlock修改操作移动赋值、交换(swap()与另一个unique_lock对象互换所管理的互斥量所有权)、释放(release()返回它所管理的互斥量对象的指针并释放所有权)获取属性owns_lock(返回当前对象是否上了锁)、operator bool()(与owns_lock()的功能相同)、mutex(返回当前unique_lock所管理的互斥量的指针)。
总的来说unique_lock类模板与lock_guard类似都提供了一种方便且安全地管理互斥量的方法。它们通过RAII的思想在对象的生命周期中自动管理锁的上锁和解锁操作从而简化了编程过程减少了出错的可能性并提高了代码的可读性和可维护性。
3. 使用示例
当使用 unique_lock 时一般需要搭配一个 std::mutex 来进行线程间同步。以下是一个简单的示例
#include iostream
#include thread
#include mutexstd::mutex mtx; // 创建一个互斥量void work_in_critical_section() {std::unique_lockstd::mutex lock(mtx); // 在进入临界区之前使用 unique_lock 对互斥量进行上锁操作// 在这里执行需要互斥访问的操作std::cout Critical section is locked by this thread std::endl;
} // 离开作用域时unique_lock 的析构函数会自动解锁互斥量int main() {std::thread t1(work_in_critical_section);std::thread t2(work_in_critical_section);t1.join();t2.join();return 0;
}在这个示例中我们创建了一个互斥量 mtx然后在 work_in_critical_section 函数中我们使用 std::unique_lock 对 mtx 进行上锁操作。在 main 函数中我们创建了两个线程分别执行 work_in_critical_section 函数。由于使用了 unique_lock它会在离开作用域时自动解锁互斥量确保线程安全。
四、总结
RAII机制是一种重要的编程范式Lock_guard和Unique_lock是C标准库中用于资源管理的类模板。它们都基于RAII机制能够简化资源的管理提高代码的可读性和可维护性。同时它们也提供了对互斥量的自动上锁和解锁操作确保了线程安全。
温馨提示
感谢您对博主文章的关注与支持另外我计划在未来的更新中持续探讨与本文相关的内容会为您带来更多关于C以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新不要错过任何精彩内容
再次感谢您的支持和关注。期待与您建立更紧密的互动共同探索C、算法和编程的奥秘。祝您生活愉快排便顺畅