1. Pthread互斥锁以及Pthread信号量的创建等相关函数
在pthread.h中有
a) pthread_mutex_t数据类型用来声明互斥锁;
b) 函数pthread_mutex_init(&mutex,NULL)用来创建互斥锁,其中第一个参数为声明的互斥锁指针,第二个参数即设置初始值,NULL表示设置为默认值;
c) 函数pthread_mutex_lock()和pthread_mutex_unlock()用来获取与释放锁。
互斥锁作用机理:
当调用pthread_mutex_lock()函数时,如果互斥锁不可用,那么调用线程会阻塞知道互斥锁占有pthread_mutex_unlock()函数为止。所以互斥函数正确执行时,返回0,否则会返回非0错误码。
而信号量的创建如下:
a) 在semaphore.h中,数据结构sem_t用来声明信号量;
b) 而sem_init()函数用来创建并且初始化一个信号量,其函数原型为:
externint sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
这个函数有三个参数,第一个为信号量的指针,第二个表示共享级别,如果为0则只能由创建本县城的进程的其他线程所共享,如果是非0值,那么可以由其他进程访问;第三个表示信号量的初始值。
c) 而sem_wait()与sem_post()则相当于PV操作。
2. 编码实现
源码有点儿长,所以贴一下关键功能:
缓冲区大小以及定义:
生产者
消费者:
信号量初始化设置:
线程创建及其数目:
插入数据: 删除数据:
思路及结果分析
生产者共排两条队,一个为等待EMPTY,即等待有空位,EMPTY初始为5;然后再等待互斥锁;
消费者也是排两条队,一个为等待FULL,即等货架上有东西,FULL初始为0;然后再等待互斥锁。
而对于缓冲区而言,缓冲区大小为5个int的大小,生产者对缓冲区的操作为向缓冲区插入数据,在此处设置了一个全局变量int i=0,生产者写入地址为buffer[i],如果写入成功,则i+=1,消费者读取地址为buffer[i-1],若消费者读取成功,则i-=1。
而程序运行时间由argv[1]觉得,单位为秒;生产者个数由argv[2]决定,消费者个数由argv[3]决定。理论上不会出现deadlock等情况。
结果如下:
以上是./cache 13 3 指令结果的最后部分,由于1秒钟生产者和消费者疯狂操作,不易于分析。所以对源码进行了一定了修改,例如将sleep()换成了usleep()以微秒作为单位,并且为了不让上述图中生产一个就吃一个的情况发生的如此理所应当,所以对rand()函数以时间播种,避免上述情况固定模式,并且设置的生产者大于消费者,使得便于观察。最终易于分析的版本如下:
./cache 1000 3 1
./cache 1000 3 2
./cache 1000 5 1
./cache 1000 5 2
由以上结果可以看出,该设计不会发生deadlock,并且可以看出生产者均没有过度生产,消费者也没有过度消费等情况。