互斥锁
mutex是最常见的多线程同步的方法。多线程共享一个互斥量,得到锁的线程可以进入临界区执行代码。
mutex是睡眠等待(sleep waiting)类型的锁,当线程抢互斥锁失败的时候,线程会陷入休眠。优点就是节省CPU资源,缺点就是休眠唤醒会消耗一点时间。
C语言的demo1
// 声明一个互斥量
pthread_mutex_t mtx;
// 初始化
pthread_mutex_init(&mtx, NULL);
// 加锁
pthread_mutex_lock(&mtx);
// 解锁
pthread_mutex_unlock(&mtx);
// 销毁
pthread_mutex_destroy(&mtx);
#include
#include
#include
pthread_mutex_t mutex;
char* buf[5];
int pos;
void* task(void *p) {
pthread_mutex_lock(&mutex);
buf[pos] = (char*)p;
sleep(1);
++ pos;
pthread_mutex_unlock(&mutex);
}
int main() {
pthread_mutex_init(&mutex, NULL);
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, task, (void*)"zhangfei");
pthread_create(&tid2, NULL, task, (void*)"guanyu");
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mutex);
int i = 0;
for (; i < pos; ++ i) {
printf("%sn", buf[i]);
}
return 0;
}
C++的demo2C++11的mutex
头文件
Mutex 系列类(四种)
std::mutex 是C++11 中最基本的互斥量红旗linux系统下载,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。
c++的demo2
#include
#include
#include
using namespace std;
mutex mtx;
int pos;
char* buf[5];
void task(const char* p) {
mtx.lock();
buf[pos] = const_cast(p);
++ pos;
mtx.unlock();
}
int main() {
thread t1(task, "zhangfei");
thread t2(task, "guanyu");
t1.join();
t2.join();
for (int i = 0; i < pos; i ++) {
cout << buf[i] << endl;
}
return 0;
}
条件变量
条件变量不是锁,它是一种线程间的通讯机制,并且几乎总是和互斥量一起使用的。所以互斥量和条件变量二者一般是成套出现的。比如C++11中也有条件变量的API: std::condition_variable。
读写锁
读写锁linux 信号量 互斥锁,就是对于临界区区分读和写。在读多写少的场景下,不加区分的使用互斥量显然是有点浪费的。
读写锁的特性:
自旋锁
自旋锁(busy waiting)linux串口驱动,只不过自旋锁不会引起线程休眠。当共享资源的状态不满足的时候,自旋锁会不停地循环检测状态。因为不会陷入休眠linux 信号量 互斥锁,而是忙等待的方式也就不需要条件变量。
这是优点也是缺点。不休眠就不会引起上下文切换,但是会比较浪费CPU。
reference
[1]
[2]
[3]