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