知识梳理------线程同步

一、为什么要线程同步
当多个控制线程共享相同的内存时,需要每个线程看到一致的数据视图。

  • 共享资源,多个线程都可对共享资源操作
  • 线程操作共享资源的先后顺序不确定
  • 处理器对存储器的操作一般不是原子操作

二、互斥量
<1> 互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量加锁之后,任何视图再次对互斥量加锁的线程都将被阻塞,直到给互斥量加锁的线程对互斥量解锁为止。
<2> 互斥量的初始化
互斥量用 pthread_mutex_t 数据类型表示,在互斥量使用之前,必须进行初始化。初始化由两种方式:

1) 对于静态分配的互斥量,通常把它置为PTHREAD_MUTEX_INITIALIZER
2) 对于动态分配的互斥量
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t* attr);

int pthread_mutex_destroy(pthread_mutex_t* mutex);

<3> 对互斥量加锁/解锁

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);//加锁的非阻塞版本
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 注意,要对互斥量解锁,必须由之前对互斥量进行加锁操作的线程来完成。

<4> 简单的例子

/*
一个生产者,一个消费者,生产者生产产品放在临界区,消费者从临界区取出产品进行消费(设定生产产品的总个数为MAX_NUM,临界区的最大容量为MAX)
*/

#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>

struct msg{
    struct msg *next;
    int num;
    msg(int x):num(x), next(NULL){};
};
struct msg *head = NULL;

int count = 0;            // 临界区当前由多少个产品
static int MAX = 5;       // 临界区大小
static int MAX_NUM = 20;  // 总共要生产的产品数量
int flage = 1;            // 标记是否已经生产完毕

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 初始化互斥量

void *produce(void* ptr);
void *consume(void* ptr);

int main()
{
    pthread_t tid_produce, tid_consume;
    srand(time(NULL));

    pthread_create(&tid_produce, NULL, produce, NULL);
    pthread_create(&tid_consume, NULL, consume, NULL);
    pthread_join(tid_produce, NULL);
    pthread_join(tid_produce, NULL);

    return 0;
}

void *produce(void* ptr){
    struct msg *mp = NULL;
    int current = 0;   //表示已经生产的个数
    while(1){
        if(count < MAX && current < MAX_NUM){
            mp = (struct msg*)malloc(sizeof(struct msg));
            mp->num = rand()%100 + 1;
            count += 1;
            current += 1;
            printf("Produce %d\tnow count = %d\tcurrent = %d\n", mp->num, count, current);
            pthread_mutex_lock(&lock);
            mp->next = head;
            head = mp;
            pthread_mutex_unlock(&lock);
        }else if(current == MAX_NUM){
            flage = 0;
            pthread_exit(0);
        }
        sleep(rand()%5);
    }
}

void *consume(void* ptr){
    struct msg *mp = NULL;
    while(1){
        if(head == NULL && !flage){
        //表示已经生产了指定数目的产品且已经全部消费完毕
            break;
        }
        pthread_mutex_lock(&lock);
        if(head == NULL){
        // 表示临界区内的产品已经消消费完毕,但生产者还会继续生产。此时,需要释放锁,使得produce由得到锁的机会
            pthread_mutex_unlock(&lock);
            sleep(read()%5);
            continue;
        }
        mp = head;
        head = mp->next;
        count -= 1;
        printf("Consume %d\tthen count = %d\n", mp->num, count);
        free(mp);
        pthread_mutex_unlock(&lock);
        sleep(rand()%5);
    }
    pthread_exit(0);
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值