网站页面结构怎么做有利于优化,资讯门户网站,网站备案号规则,厦门网站公司文章目录 互斥量如何理解互斥量C 中互斥量的用法基本锁定和解锁使用 std::lock_guard 自动管理锁使用 std::unique_lock 获得更多控制 注意事项 几种不同类型的锁 创建一个C线程需要传入几个参数#xff1f; 如何理解和使用C线程循环 C 类 函数 变量 进程 线程 C关于锁和互斥量… 文章目录 互斥量如何理解互斥量C 中互斥量的用法基本锁定和解锁使用 std::lock_guard 自动管理锁使用 std::unique_lock 获得更多控制 注意事项 几种不同类型的锁 创建一个C线程需要传入几个参数 如何理解和使用C线程循环 C 类 函数 变量 进程 线程 C关于锁和互斥量你真的理解了吗 C 代码中如何使用互斥锁std::mutex和独占锁std::unique_lock
互斥量
在 C 中互斥量Mutex即 Mutual Exclusion是并发编程中的一种基本工具用于控制多个线程对共享资源的访问以防止数据竞争和相关的未定义行为。互斥量提供了一种机制允许一个线程一次只锁定一次资源确保在该线程释放互斥量之前其他线程不能访问被保护的资源。
如何理解互斥量
互斥量可以被视为一种锁用来保护共享数据确保在任何时候只有一个线程可以访问这些数据。当一个线程需要访问被互斥量保护的资源时它必须先锁定acquire这个互斥量。如果互斥量已被另一个线程锁定该线程将被阻塞直到互斥量被释放unlock。这防止了多个线程同时读写同一数据从而防止了数据损坏和不一致性。
C 中互斥量的用法
C 标准库提供了 mutex 头文件其中包含用于管理互斥量的类。最常用的类是 std::mutex。以下是 std::mutex 的基本用法
基本锁定和解锁
#include iostream
#include mutexstd::mutex mtx; // 定义一个互斥量void function() {mtx.lock(); // 锁定互斥量// ... 执行需要互斥的操作 ...mtx.unlock(); // 解锁互斥量
}#include iostream
#include mutexstd::mutex mtx; // 全局互斥锁void print_function(const std::string message) {mtx.lock(); // 手动锁定std::cout message std::endl;mtx.unlock(); // 手动解锁
}int main() {print_function(Hello from main function);return 0;
}main 函数直接调用 print_function而不是创建新线程来调用它。print_function 依然使用 mtx.lock() 和 mtx.unlock() 来手动管理互斥锁尽管在单线程环境中这实际上是不必要的。
请注意在单线程程序中使用互斥锁通常是没有必要的因为没有并发访问共享资源的风险。此示例仅用于说明如何单独使用 std::mutex。在实际应用中您应该根据程序的并发需求来决定是否使用互斥锁。
使用 std::lock_guard 自动管理锁
为了避免忘记解锁或在异常发生时遗漏解锁可以使用 std::lock_guard它提供了一种自动管理锁的方法RAII资源获取即初始化。
void safe_function() {std::lock_guardstd::mutex lock(mtx);// ... 执行需要互斥的操作 ...
} // lock_guard 在作用域结束时自动释放互斥量使用 std::unique_lock 获得更多控制
std::unique_lockstd::mutex 提供了比 std::lock_guard 更多的灵活性允许你延迟锁定重复锁定和解锁以及移动锁。
void flexible_function() {std::unique_lockstd::mutex lock(mtx, std::defer_lock);// ... 这里互斥量还未锁定 ...lock.lock(); // 手动锁定// ... 执行需要互斥的操作 ...lock.unlock(); // 可以手动解锁// ... 可以在不同的时间点再次锁定 ...
}注意事项
避免死锁确保在所有路径上无论是正常还是异常锁都能被释放。std::lock_guard 和 std::unique_lock 在这方面非常有用。锁的粒度锁应该保护的是访问共享资源的最小必要代码区域以避免不必要的性能损失。不要过度使用互斥量在不需要保护共享资源的地方不要使用互斥量以免引入不必要的性能开销和复杂性。
正确地使用互斥量可以确保多线程程序的正确性和稳定性但需要谨慎使用以避免常见的陷阱如死锁和性能瓶颈。
几种不同类型的锁
在 C 中除了 std::mutex标准库提供了几种不同类型的锁以适应不同的并发和同步需求。下面是一些常见的锁类型及其简要说明 std::mutex: 最基本的互斥锁用于保护共享数据防止多个线程同时访问。std::mutex 提供了基本的锁定和解锁功能但没有递归锁定的能力。 std::recursive_mutex: 递归互斥锁允许同一线程多次获取锁。如果一个线程已经持有该锁它可以再次锁定而不会产生死锁。这对于递归函数或可重入函数很有用。 std::timed_mutex: 带有超时功能的互斥锁。它允许尝试锁定一个互斥锁直到指定的时间点或者经过指定的时间段。如果在指定时间内无法获得锁则返回。 std::recursive_timed_mutex: 结合了 std::recursive_mutex 和 std::timed_mutex 的特性。它是一个可以由同一线程多次锁定的互斥锁同时提供了带超时的锁定尝试。 std::shared_mutex (C17): 允许多个线程同时读取共享数据但写操作是互斥的。这对于读多写少的场景非常有用。 std::shared_timed_mutex (C14): 是 std::shared_mutex 的一个变体提供了超时功能。它允许多个线程同时进行读取操作但写入操作将独占锁定。 std::lock_guard: 是一个作用域锁它在构造时自动锁定给定的互斥锁并在析构时自动解锁。它提供了一种方便的方式来确保在作用域结束时释放互斥锁。 std::unique_lock: 比 std::lock_guard 更灵活的作用域锁。它不仅允许在构造时延迟锁定还可以在生命周期内多次锁定和解锁互斥锁。
这些锁的选择和使用取决于特定的应用场景和性能要求。例如对于简单的互斥需求std::mutex 和 std::lock_guard 通常就足够了。而对于需要更精细控制的场景如需要超时或递归锁定功能你可能需要选择 std::timed_mutex 或 std::recursive_mutex 等更高级的锁类型。