线程同步与互斥实验_mutex互斥锁_cond条件变量

学校OS操作系统讲解mutex和cond后的实验。

  • 实验项目名称

    线程同步与互斥

  • 实验目的
  1. 掌握线程的API函数
  2. 能够区分多线程执行结果产生错误的原因,并能够使用同步和互斥解决问题。
  • 实验要求

主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数  ->  sleep(50)  ->  全局变量++  ->  sleep(0)  ->  输出参数和全局变量。

要求:

1.子线程输出的线程序号不能重复。

2.全局变量的输出必须递增。

附加要求:

  1. 按序号次序输出

可以使用两种方法,第一种只用mutex互斥锁(那这节课讲的cond条件变量就没什么用了doge),第二种是使用mutex和cond。

法一:mutex

        每次create完再join等待线程结束。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;


int count;

void* mythread(void * arg){
	sleep(2); //sleep(50)
	pthread_mutex_lock(&lock);
	count++;
	pthread_mutex_unlock(&lock);
	sleep(0);
	printf("线程 %d  count : %d\n", (int) arg, count);
	return NULL;
}

int main(){
	pthread_mutex_init(&lock, NULL);
	pthread_t p[10];
	int i = 0;
	for(; i < 10; i ++){
		pthread_create(&p[i], NULL, mythread, (void*) i);		
		pthread_join(p[i], NULL);
	}
	
	pthread_mutex_destroy(&lock);
	return 0;
}

 CentOS运行结果:

法二:mutex + cond

        因为create调用线程后,各个线程的执行顺序是随机的,要使后面按照线程序号唤醒各个线程,就要依次将各个线程放入wait休眠队列,这样在signal唤醒线程时才能依次发出信号。

        使用了tiket将线程依次进行休眠。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int count;
int tiket = 1;

void* mythread(void * arg){
	int tmp = (int) arg;
	printf("enter pthread:%d	\n", tmp);
	
	while(!tmp) //特判第一个线程(线程0)
		if(tiket == tmp) break; //后序线程全部按序进行wait休眠队列后,break
	
	while(tiket != tmp){
            //很愚蠢的自旋,为了让各个线程按照次序进行休眠
	}

	pthread_mutex_lock(&lock);
	
	
	if(tmp){ //非第一个线程
		tiket = (tiket + 1) % 10;
		printf("	pthread %d ready to wait\n", tmp); 
		pthread_cond_wait(&cond, &lock); //进入休眠队列
	}
	
    //开始进行对全局变量的++操作。
	sleep(2);  //sleep(50)
	count++;
	tiket++;
	printf("pthread %d  count : %d\n", tmp, count);
	printf("		ready to call pthread %d\n", tiket);
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&lock);
	sleep(0);
	
	return NULL;
}

int main(){
	pthread_mutex_init(&lock, NULL);
	pthread_t p[10];
	int i = 0;
	for(; i < 10; i ++){
		pthread_create(&p[i], NULL, mythread, (void*) i); //传入线程序号i
	} 
	for(i = 0; i < 10; i ++){
		pthread_join(p[i], NULL);		
	}
	
	pthread_mutex_destroy(&lock);
	pthread_cond_destroy(&cond);
	return 0;
}

CentOS运行结果:

可以看出,每次create后,各个线程的运行是随机的,并不会按照create的调用顺序来运行线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值