目录
一、什么是互斥锁
1、定义
互斥锁(Mutual Exclusion Lock)是一种机制,用于确保同一时间只有一个线程可以访问特定的共享资源。它类似于一把“锁”,只有获取了这把锁的线程才能访问被保护的资源。
2. 工作原理
- 加锁:当一个线程需要访问共享资源时,它首先需要获取互斥锁。如果锁当前没有被其他线程持有,线程将成功获得锁并进入临界区(即访问共享资源的代码部分)。
- 解锁:当线程完成对共享资源的访问后,它必须释放互斥锁,使其他等待中的线程可以继续访问共享资源。
- 阻塞:如果另一个线程试图获取一个已经被持有的锁,该线程将被阻塞(即等待),直到锁被释放。
3. 避免问题
- 死锁:如果多个线程在持有锁时都等待对方释放锁,就会发生死锁。为了避免死锁,可以设计合理的锁获取顺序,或者使用超时机制。
- 饥饿:如果某些线程总是得不到锁,可能会导致饥饿现象。可以通过公平的锁策略(例如公平锁)来减少这种情况的发生。
4. 实现方式
互斥锁的实现可以基于操作系统提供的原语,比如互斥量(mutex),信号量(semaphore),或者基于自旋锁(spinlock)等技术。
#include <iostream> #include <pthread.h> #include <unistd.h> // 用于 sleep 函数 // 定义互斥锁 pthread_mutex_t mutex; // 线程函数 void* threadFunction(void* arg) { // 尝试获取互斥锁 pthread_mutex_lock(&mutex); // 临界区开始:访问共享资源 std::cout << "线程 " << pthread_self() << " 进入临界区" << std::endl; sleep(1); // 模拟对共享资源的操作 std::cout << "线程 " << pthread_self() << " 离开临界区" << std::endl; // 释放互斥锁 pthread_mutex_unlock(&mutex); return nullptr; } int main() { // 初始化互斥锁 if (pthread_mutex_init(&mutex, nullptr) != 0) { std::cerr << "无法初始化互斥锁" << std::endl; return 1; } const int NUM_THREADS = 5; pthread_t threads[NUM_THREADS]; // 创建多个线程 for (int i = 0; i < NUM_THREADS; ++i) { if (pthread_create(&threads[i], nullptr, threadFunction, nullptr) != 0) { std::cerr << "无法创建线程 " << i << std::endl; return 1; } } // 等待所有线程完成 for (int i = 0; i < NUM_THREADS; ++i) { pthread_join(threads[i], nullptr); } // 销毁互斥锁 pthread_mutex_destroy(&mutex); return 0; }
5. 使用场景
互斥锁广泛应用于各种需要保护共享资源的场景,如多线程程序中的数据结构操作、文件读写、网络通信等。
总之,互斥锁是一种非常重要的同步工具,正确使用它可以有效避免并发编程中的许多常见问题,提高程序的安全性和稳定性。