linux pthread 互斥锁 读写锁 自旋锁

1. 概述:
该demo主要实现了linux下通过锁的方式模拟生产者消费者的场景,相关接口介绍可以参考<<UNIX环境高级编程>>
在这里插入图片描述

2. 场景(生产者->消费者):
1)生产者:
当食物数量小于最大值且大于0时, 不断生产食物;
否则当食物为0时,退出线程
2) 消费者:
当食物数量大于0时, 不断消费食物;
否则当食物为0时,退出线程

3. 测试:
在这里插入图片描述

/*
pthread_tip.h
线程锁相关接口介绍 : 互斥锁, 读写锁, 自旋锁

原子性 : 加锁解锁属于原子操作

互斥锁 : 
        非繁忙等待 : 阻塞时不占用cpu资源

读写锁(共享互斥锁) : 
        如果有线程读操作, 则允许其它线程执行读操作, 但不允许写操作
        如果有线程写操作, 则不允许其它线程执行读写操作
        适用于读操作比写操作多得多的情况

自旋锁 : 
        繁忙等待 : 阻塞时占用cpu资源
        适用于锁的持有时间比较短, 或者说小于2次上下文切换时间的情况

*/
#include <pthread.h>
#include <time.h>

/******************************互斥锁*************************************/
//静态初始化, 采用默认的attr
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

//动态初始化
int pthread_mutex_init(pthread_mutex_t * mutex, 
                                const pthread_mutexattr_t * attr);

//释放资源
int pthread_mutex_destroy(pthread_mutex_t *mutex);

//请求锁, 如果当前mutex已经被锁, 线程会处于阻塞状态, 直到mutex被释放
int pthread_mutex_lock(pthread_mutex_t *mutex);

//尝试请求锁, 如果当前mutex已经被锁或者不可用, 直接返回失败
int pthread_mutex_trylock(pthread_mutex_t *mutex);

//超时指定愿意等待的绝对时间(与相对时间对比而言, 指定在时间x之前可以阻塞等待, 而不是说愿意阻塞Y秒)
int pthread_mutex_timedlock(pthread_mutex_t * mutex,
                                        const struct timespec * tsptr);

//解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);


/******************************读写锁*************************************/
static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

int pthread_rwlock_init(pthread_rwlock_t * rwlock, 
                                    const pthread_rwlockattr_t * attr);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_mutex_timedrdlock(pthread_rwlock_t * rwlock,
                                        const struct timespec * tsptr);

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_mutex_timedwrlock(pthread_rwlock_t * rwlock,
                                        const struct timespec * tsptr);

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);


/******************************自旋锁*************************************/
/*
pshared : 进程共享属性
        PTHREAD_PROCESS_SHARED  : 支持多进程(共享内存)
        PTHREAD_PROCESS_PRIVATE : 仅支持单进程
*/
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);

int pthread_spin_destroy(pthread_spinlock_t *lock);

int pthread_spin_lock(pthread_spinlock_t *lock);

int pthread_spin_trylock(pthread_spinlock_t *lock);

int pthread_spin_unlock(pthread_spinlock_t *lock);
/*
demo_pthread_mutex.c
线程编程demo : 互斥锁的基本使用

pthread并非Linux系统的默认库, 而是POSIX线程库
在Linux中将其作为一个库来使用, 因此加上 -lpthread(或-pthread)以显式链接该库

*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define MAX_FOOD    5

/*
互斥锁
*/
/*
静态初始化
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
*/
static pthread_mutex_t s_mutex;

static unsigned int s_food = MAX_FOOD;

typedef enum operate{
    UP,
    DOWN,
    OUT
} OPERATE;

static int Operate(unsigned int * pfood, OPERATE enoperate){

    if(pfood == NULL){
        return -1;
    }

    unsigned int food = * pfood;

    /*
    非阻塞的,调用后立即返回 
    int pthread_mutex_trylock(pthread_mutex_t *mutex) 
    */

    /*
    超时指定愿意等待的绝对时间
    int pthread_mutex_timedlock(pthread_mutex_t * mutex,const struct timespec * tsptr)
    */

    if (pthread_mutex_lock(&s_mutex) != 0){
        printf("pthread_mutex_lock err\n");
        return -1;
    }

    switch(enoperate){
        case UP:
            food ++;
            break;

        case DOWN:
            food --;
            break;

        default :
            return -1;
    }

    if (pthread_mutex_unlock(&s_mutex) != 0){
        printf("pthread_mutex_unlock err\n");
        return -1;
    }

    s_food = food;
    * pfood = s_food;

    return 0;
}

static int Get(unsigned int * pfood){

    if(pfood == NULL){
        return -1;
    }

    if (pthread_mutex_lock(&s_mutex) != 0){
        printf("pthread_mutex_lock err\n");
        return -1;
    }

    unsigned int food = s_food;

    if (pthread_mutex_unlock(&s_mutex) != 0){
        printf("pthread_mutex_unlock err\n");
        return -1;
    }

    * pfood = food;

    return 0;
}

/*
生产者
*/
static void * pthread_producer(void *arg)
{
    int ret = 0;
    unsigned int food = 0;

    while(1){

        food = 0;
        ret = Get(&food);
        if(ret < 0){
            printf("Get err\n");
            continue;
        }

        if(food == 0){
            break;
        }

        if(food < MAX_FOOD){
            ret = Operate(&food, UP);
            if(ret < 0){
                printf("Operate err\n");
                continue;
            }
        }
        else {
            continue;
        }

        printf("pthread_producer = %d\n", food);

        usleep(50 * 1000);
    }

    return NULL;
}

/*
消费者
*/
static void * pthread_consumer(void *arg)
{
    int ret = 0;
    unsigned int food = 0;

    while(1){

        food = 0;
        ret = Get(&food);
        if(ret < 0){
            printf("Get err\n");
            continue;
        }

        if(food == 0){
            break;
        }

        if(food > 0){
            ret = Operate(&food, DOWN);
            if(ret < 0){
                printf("Operate err\n");
                continue;
            }
        }
        else{
            continue;
        }

        printf("pthread_consumer = %d\n", food);

        usleep(20 * 1000);
    }

    return NULL;
}

int main(int argc, char **argv){

    pthread_t pid_producer;
    pthread_t pid_consumer;
    int ret = 0;
    unsigned int food = 0;

    /*
    动态初始化
    */
    if (pthread_mutex_init(&s_mutex, NULL) != 0){
       printf("pthread_mutex_init err\n");
       return -1;
    }

    /* 主线程开始运行 */
    printf("main start!\n");

    food = 0;
    ret = Get(&food);
    if(ret < 0){
        printf("Get err\n");
        return -1;
    }
    printf("main = %d\n", food);

    /*
    创建线程
    */
    if (pthread_create(&pid_producer, NULL, pthread_producer, NULL) != 0){
        printf("pthread_create err\n");
        return -1;
     }
    if (pthread_create(&pid_consumer, NULL, pthread_consumer, NULL) != 0){
        printf("pthread_create err\n");
        return -1;
     }

    /* 
    回收线程资源
    */
    if (pthread_join(pid_producer, NULL) != 0){
        printf("pthread_join err\n");
    }
    if (pthread_join(pid_consumer, NULL) != 0){
        printf("pthread_join err\n");
    }

    food = 0;
    ret = Get(&food);
    if(ret < 0){
        printf("Get err\n");
        return -1;
    }
    printf("main = %d\n", food);

    /* 主线程结束运行 */
    printf("main end!\n");

    pthread_mutex_destroy(&s_mutex);

    return 0;
}
#Makefile
CC := gcc
INCLUDE = -I /home/demo/include/
LIB = -lpthread

all:
	$(CC) demo_pthread_mutex.c $(INCLUDE) $(LIB) -o demo_pthread_mutex -Wall -Werror

clean:
	rm demo_pthread_mutex
发布了12 篇原创文章 · 获赞 16 · 访问量 1736

猜你喜欢

转载自blog.csdn.net/lpaim/article/details/104335965
今日推荐