美文网首页
线程同步

线程同步

作者: StevenHD | 来源:发表于2020-11-14 10:54 被阅读0次

一、临界资源

保护临界资源的手段
  • 加锁会导致运行时间的增长

二、互斥锁

#include <stdio.h>
#include <thread>
#include <mutex>

// 临界资源
int num = 0;

std::mutex _mutex;

// 生产者
void producer() {
    
    for (int i = 0; i < 1e7; i++)
    {
        _mutex.lock();
        num += 1;
        _mutex.unlock();
    }
}

// 消费者
void comsumer() {
    for (int i = 0; i < 1e7; i++)
    {
        _mutex.lock();
        num -= 1;
        _mutex.unlock();
    }
}


int main() {
    printf("Start in main function.");
    std::thread pro_thread(producer), coms_thread(comsumer);

    pro_thread.join();
    coms_thread.join();

    printf("Print in main function: num = %d\n", num);
    return 0;
}

三、自旋锁

  • 实验发现【自旋锁】的效率较高


    自旋锁
死循环
  • 自旋锁加入休眠的话会产生死锁
#include <stdio.h>
#include <thread>
#include <atomic>

using namespace std;
using namespace this_thread;
using namespace chrono;

class Spin_lock 
{
public:
    Spin_lock() = default;
    Spin_lock(const Spin_lock&) = delete;
    Spin_lock& operator=(const Spin_lock&) = delete;
    ~Spin_lock() = default;

    void lock();
    void unlock();

private:
    std::atomic_flag flag;
};

void Spin_lock::lock()
{
    while (flag.test_and_set());
}

void Spin_lock::unlock()
{
    flag.clear();
}

Spin_lock spinlock;

// 临界资源
int num = 0;

// 生产者
void producer() {
    
    for (int i = 0; i < 1e4; i++)
    {
        spinlock.lock();
        num += 1;
        spinlock.unlock();
    }
}

// 消费者
void comsumer() {
    for (int i = 0; i < 1e4; i++)
    {
        spinlock.lock();
        num -= 1;
        sleep_for(milliseconds(100));
        spinlock.unlock();
    }
}


int main() {
    printf("Start in main function.");
    std::thread pro_thread(producer), coms_thread(comsumer);

    pro_thread.join();
    coms_thread.join();

    printf("Print in main function: num = %d\n", num);
    return 0;
}

参考博客

四、读写锁

读写锁介绍

五、条件变量

  • 条件变量是允许线程睡眠的


    条件变量
条件变量来实现唤醒

条件变量需要配合互斥量来使用

条件变量
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

const int MAX_BUF = 100;
int num = 0;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* producer(void*)
{
    while (1)
    {
        pthread_mutex_lock(&mutex);
        while (num >= MAX_BUF)
        {
            // wait and sleep
            printf("buffer is enough, so wait consumer to save..\n");
            pthread_cond_wait(&cond, &mutex);
        }
        num += 1;
        printf("Produce a product, current product's num is: %d\n", num);
        sleep(1);
        pthread_cond_signal(&cond);
        printf("inform consumer\n");
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

void* consumer(void*)
{
    while (1)
    {
        pthread_mutex_lock(&mutex);
        while (num <= 0)
        {
            // wait and sleep
            printf("buffer is null, so wait producer to save..\n");
            pthread_cond_wait(&cond, &mutex);
        }
        num -= 1;
        printf("Consume a product, current product's num is: %d\n", num);
        sleep(1);
        pthread_cond_signal(&cond);
        printf("inform producer..\n");
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    printf("Start in main function.\n");
    pthread_t thread1, thread2;

    pthread_create(&thread1, NULL, &producer, NULL);
    pthread_create(&thread2, NULL, &consumer, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("Print in main function: num = %d\n", num);
    return 0;
}

六、线程同步总结

锁的总结
对比

相关文章

网友评论

      本文标题:线程同步

      本文链接:https://www.haomeiwen.com/subject/lkgibktx.html