linux多线程同步——互斥锁、条件变量、读写锁、自旋锁、信号量

互斥锁

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 <stdio.h>
#include <pthread.h>
#include <unistd.h>

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("%s
", buf[i]);
    }
    return 0;
}

C++的demo2

C++11的mutex

<mutex> 头文件
Mutex 系列类(四种)

  • std::mutex,最基本的 Mutex 类。
  • std::recursive_mutex,递归 Mutex 类。
  • std::time_mutex,定时 Mutex 类。
  • std::recursive_timed_mutex,定时递归 Mutex 类

std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。

c++的demo2

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

mutex mtx;
int pos;
char* buf[5];

void task(const char* p) {
    mtx.lock();
    buf[pos] = const_cast<char*>(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。

读写锁

读写锁,就是对于临界区区分读和写。在读多写少的场景下,不加区分的使用互斥量显然是有点浪费的。

读写锁的特性:

  • 当读写锁被加了写锁时,其他线程对该锁加读锁或者写锁都会阻塞(不是失败)。
  • 当读写锁被加了读锁时,其他线程对该锁加写锁会阻塞,加读锁会成功。

自旋锁

自旋锁(busy waiting),只不过自旋锁不会引起线程休眠。当共享资源的状态不满足的时候,自旋锁会不停地循环检测状态。由于不会陷入休眠,而是忙等待的方式也就不需要条件变量。

这是优点也是缺点。不休眠就不会引起上下文切换,但是会比较浪费CPU。

reference

[1] https://www.cnblogs.com/cangqinglang/p/13328217.html
[2] https://mp.weixin.qq.com/s/z297vQBfraPn8IzbV9VXUQ
[3] https://www.cnblogs.com/haippy/p/3237213.html

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...