进程同步与互斥:LINUX环境

本文主要介绍了在LINUX环境下如何实现进程的同步与互斥,讲解了线程函数如pthread_create、pthread_join等的使用,以及互斥锁和信号量的详细操作。通过生产者消费者问题和哲学家就餐问题,阐述了同步互斥的重要性,并提供了实现同步互斥的代码框架。
摘要由CSDN通过智能技术生成

一、实验目的
1. 掌握基本的同步与互斥算法,理解P,V操作。
2. 理解生产者消费者模型,了解其它典型的同步互斥模型,如哲学家就餐、读者-写者模型等。
3. 了解LINUX中进程同步互斥的实现方法,掌握相关函数的使用方法。
4. 学习使用Windows中基本的同步对象,掌握相关API的使用方法。
5. 了解Windows中多线程的并发执行机制,实现进程的同步与互斥。
二、实验环境
LINUX环境

三、实验内容:
PART 1 LINUX环境
一、相关知识介绍
1.常用线程函数
pthread线程库的使用,在源码中使用头文件 pthread.h,用gcc链接时加上 -lpthread 选项,链接线程库。
(1) pthread_create 创建一个线程
int pthread_create(pthread_t *thread, const pthread_attr_t attr,voidstart_rtn)(void),void * arg);
 参数1:产生线程的标识符
 参数2:所产生线程的属性,通常设为NULL
参数3:新的线程所执行的函数
参数4:新的线程函数的参数
函数返回值:若线程创建成功则返回0,否则返 回-1.

(2) pthread_exit 线程自行退出

(3) pthread_join 其它线程等待某一个线程退出
int pthread_join( pthread_t thread , void **value_ptr);
 参数1:等待线程的标识符
 参数2:用户定义的指针,用来存储被等待线程的返回值
函数返回值:若执行成功则返回0,失败返回错误号, 如果一个线程要等待另一个线程的终止,则使用该函数

(4) pthread_cancel 其它线程强行杀死某一个线程

  1. 互斥锁使用方法
    (1) 互斥锁操作相关函数
    pthread_mutex_init: 互斥量初始化
    pthread_mutex_lock: 互斥量加锁
    pthread_mutex_unlock: 释放互斥锁
    pthread_mutex_destroy: 释放互斥锁资源
    (2)使用互斥锁对临界区进行操作的方法:
    使用函数pthread_mutex_lock进行加锁
    临界区操作
    使用函数pthread_mutex_unlock释放互斥锁

  2. 信号量使用方法
    (1) 信号量相关函数
    信号量的数据类型为sem_t
    #include<semaphore.h>
    相关函数: sem_init 、sem_wait、 sem_post、 sem_destroy
    int sem_init (sem_t *sem, int pshared, unsigned int value);
    参数1: 待初始化的信号量
    参数2: 信号量的类型。如果值为0,表示是当前进程的局部信号量,否则是其它进程可以共享该信号量。 LINUX线程一般不支持进程间共享信号量,该值设为0.
    参数3:信号量的初始值。
    调用成功时返回0,失败返回-1.

int sem_wait(sem_t * sem);
参数: 由sem_init调用初始化的信号量对象的指针 sem的值减1等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。如果信号量的值为0,则线程阻塞。相当于P操作。
成功返回0,失败返回-1

int sem_post(sem_t * sem);
参数: 由sem_init调用初始化的信号量对象的指针
释放信号量,让信号量的值加1。相当于V操作。

int sem_destroy(sem_t * sem);
参数: 由sem_init调用初始化的信号量对象的指针
归还自己占据的一切资源。 在清理信号量的时候如果还有线程在等待它,用户就会收到一个错误。

(2) 信号量使用方法
声明一个信号量sem_t my_sem;
初始化信号量sem_init(& my_sem,0,1);
sem_post和sem_wait函数配合使用来达到线程同步
释放信号量int sem_destroy (& my_sem);

二、实验内容

  1. 生产者-消费者问题
    (1)以下给出生产者-消费者问题的基本框架,未实现同步互斥控制,仔细查看程序运行结果,分析原因。
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#define N 4 // 消费者或者生产者的数目
#define M 20 // 缓冲数目 
int in = 0; // 生产者放置产品的位置
int out = 0; // 消费者取产品的位置 
char buff[M]; // 缓冲区 
int producter_id = 0; //生产者id
int consumer_id = 0; //消费者id
/* 打印缓冲情况 */
void print()
{
int i;
for(i = 0; i < M; i++)
printf("%c ", buff[i]);
printf("\n");
}
/* 生产者方法 */
void *producter()
{
int id = ++producter_id;
while(1)
{
// 用sleep的数量可以调节生产和消费的速度
sleep(2);
char data;
data=rand()%26+65; 
in = in % M;
printf("生产者进程%d在%2d位置产生数据%c: ", id,in,data); 
buff[in] = data; 
print(); 
++in;
}
}
/* 消费者方法 */
void *consumer()
{
char data;
int id = ++consumer_id;
while(1)
{
// 用sleep的数量可以调节生产和消费的速度
sleep(1);
out = out % M;
data=buff[out];
printf("消费者进程%d在%2d位置消费数据%c: ",id, out,data); 
buff[out] = '*';
print();
++out;
}
}
int main()
{
pthread_t p[N];
pthread_t c[N];
int i;
int ret[N];
for(i=0; i<M; i++)
buff[i]='*'; //'*'表示空,初始化缓冲区
srand((int)time(NULL));
// 创建N个生产者线程
for (i = 0; i < N; i++)
{
ret[i] = pthread_create(&p[i], NULL,(void*)producter, (void *)(&i));
if(ret[i] != 0)
{
printf("producter %d creation failed \n", i);
exit(1);
}
}
//创建N个消费者线程
for(i = 0; i < N; i++)
{
ret[i] = pthread_create(&c[i], NULL, (void*)consumer, NULL);
if(ret[i] != 0)
{
printf("consumer %d creation failed\n", i);
exit(1);
}
}
//销毁线程
for(i = 0; i < N; i++)
{
pthread_join(p[i],NULL);
pthread_join(c[i],NULL);
}
exit(0);
}

``&#
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虚神公子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值