使用线程的属性来实现消费者生产者
关于线程的属性, 需要的就是进程间内能够使用的shared属性, 也就是线程的共享.
互斥量属性的数据类型是 pthread_mutexattr_t. 下面两个函数分别用于互斥量属性的初始化与回收。
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
// 成功, 返回 0; 失败返回 -1并将错误存放在 errno中
1. /* 获取互斥量属性对象在进程间共享与否的标志 */
2. int pthread_mutexattr_getpshared (const pthread_mutexattr_t *restrict __attr, int *restrict pshared);
1. /* 设置互斥量属性对象,标识在进程间共享与否 */
2. int pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared);
pshared的值
- PTHREAD_PROCESS_PRIVATE
: 这种是默认的情况,表示互斥量只能在本进程内部使
PTHREAD_PROCESS_SHARED
:表示互斥量可以在不同进程间使用。
首先要初始化一个共享内存, 并且存入数据
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <pthread.h>
const int addr = 0x8888;
struct Produce_Consume
{
int food;
pthread_mutex_t mutex;
};
int main(int argc, char *argv[])
{
int id;
// 创建一个共享空间
if(argv[1][0] == 'i')
id = shmget(addr, sizeof(Produce_Consume), IPC_CREAT | IPC_EXCL | 0664);
else
id = shmget(addr, 0, 0);
// 设置一个线程属性
pthread_mutexattr_t mutexattr;
// 初始化属性
pthread_mutexattr_init(&mutexattr);
// 将线程属性设置为设置为在不同进程间进行同步
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
// 连接到共享内存
struct Produce_Consume *pro_con = (struct Produce_Consume *)shmat(id, NULL, 0);
// 先初始化生产的数量
pro_con->food = 2;
// 初始化结构体中的互斥锁属性
pthread_mutex_init(&pro_con->mutex, &mutexattr);
// 删除不用的属性了
pthread_mutexattr_destroy(&mutexattr);
// 将内存进行映射
shmdt((void *)pro_con);
// 删除共享内存
if(argv[1][0] == 'd')
shmctl(id, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}
在图片中, 可以看到 IPCS 指令打印了共享信息, 0x8888的地址申请成功了(忽略其他没有回收的内存…)
建立其他进程访问共享空间
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <pthread.h>
struct Produce_Consume
{
int food;
pthread_mutex_t mutex;
} * pro_con;
const int addr = 0x8888;
// 生产者
void *Pro(void *)
{
while (1)
{
pthread_mutex_lock(&pro_con->mutex);
if(pro_con->food < 5)
pro_con->food++;
printf("Produce food %d\n", pro_con->food);
pthread_mutex_unlock(&pro_con->mutex);
usleep(1000 * 500);
}
return ((void *)0);
}
// 消费者
void *Con(void *)
{
while (1)
{
pthread_mutex_lock(&pro_con->mutex);
if(pro_con->food > 0)
pro_con->food--;
printf("Consume food %d\n", pro_con->food);
pthread_mutex_unlock(&pro_con->mutex);
usleep(1000 * 500);
}
return ((void *)0);
}
int main(int argc, char *argv[])
{
int id = shmget(addr, 0, 0);
// 获取共享内存数据
pro_con = (struct Produce_Consume *)shmat(id, NULL, 0);
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, Pro, NULL);
pthread_create(&thread2, NULL, Con, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
这样就实现了线程在不同进程间的共享了. 明白了基本函数, 理解起来也就不难了, 我就是将复杂的都省去了, 错误判断都没写, 也变代码简洁, 容易理解, 希望做的朋友自己还是加上错误的处理, 增强代码健壮性.