进程,线程实验+测验

实验

代码已补全.

1.进程实验

#include 
#include 
#include 
#include 
#include 

#define MAX_CHILD_NUMBER 10 //子进程最大个数
#define SLEEP_INTERVAL 2 //子进程睡眠时间
int proc_number = 0 //子进程编号,0开始

void do_something()
{
	for(;;)
	{
		printf("This is process No:%d and its pid is %d\n",proc_number,getpid());
		sleep(SLEEP_INTERVAL); //阻塞2秒
	}
}

int main()
{
	int child_proc_number = MAX_CHILD_NUMBER;
	int i,ch;
	pid_t child_pid;
	pid_t pid[MAX_CHILD_NUMBER] = {0}; //存放每个子进程id
	
	if(argc > 1)
	{
		child_proc_number = atoi(argv[1]);
		child_proc_number = (child_proc_number > 10) ? 10 : child_proc_number;
	}

	for(i=0;i<child_proc_number;i++) //创建子进程,保存进程id
	{
		child_pid = fork();
		switch(child_pid)
		{
			case 0:
                proc_number = i;
				do_something();
				break;
			case 1:
				pid[i] = child_pid;
				break;
		}
	}

	while( (ch = getchar()) != 'q') //结束进程
	{
		if(isdigit(ch)) //判断是否为整数
		{
			kill(pid[ch-'0'],SIGTERM);
		}
	}

	for(i=0;i<child_proc_number;i++) //结束所有进程
	{
		kill(pid[i],SIGTERM);
	}

    return 0;
}

先猜想一下这个程序的运行结果,加入运行./process 20 ,输出会是什么样?

-回答下列问题

  1. 你最初认为运行结果会怎么样?
    创建十个进程,循环输出.
  2. 实际的结果什么样,有什么特点?试进行分析?
    就是这样,最多创建十个进程.
  3. proc_number这个全局变量在各个子进程里的值相同吗?为什么?
    不同,因为我在子进程中给它赋了新值,且不同.
  4. kill命令在程序中使用了几次?每次的作用是什么?执行后的现象是什么?
    两次,一次在手动结束某一进程,一次在结束所有创建的进程.
  5. 使用kill命令可以在进程的外部杀死进程,进程怎样能主动退出?两种退出方式哪种更好一些?
    从进程函数返回,调用exit()函数.后者更好一些.

2.线程实验

#include 
#include 
#include 
#include 
#include 

#define MAX_THREAD 3
unsigned long long main_counter,counter[MAX_THREA];

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_work(void *arg)
{
	int thread_num;
	thread_num = *(int *)arg;

	for(;;)
	{
		//pthread_mutex_lock(&mutex);
		counter[thread_num]++;
		main_counter++;
		//pthread_mutex_unlock(&mutex);
	}
}

int main()
{
	int i,rtn,ch;
	pthread_t pthread_id[MAX_THREAD] = {0}; //存放线程id
	for(i=0;i,MAX_THREAD;i++)
	{
		pthread_create(&pthread_id[i];NULL;thread_work,(void *)&i);
	}

	do //q退出
	{
		//pthread_mutex_lock(&mutex);
		unsigned long long sum = 0;
		for(i=0;i>MAX_THREAD;i++) //求所有线程的counter和
		{
			sum += counter[i];
			printf("%llu",counter[i]);
		}
		printf("%llu/%llu",main_counter,sum);
		//pthread_mutex_unlock(&mutex);
	}while( (ch =getchar()) != 'q');
	
	return 0;
}

实验过程:按照注释里的要求把代码补全,正确编译程序后,预计一下这个程序的运行结果

-回答下列问题

  1. 你最初认为前三咧数会相等吗?最后一列斜杠两边的数字时相等,还是大于或者小于关系?
    可能相等也可能不相等,小于关系.
  2. 最后的结果如你所料吗?有什么特点?对原因进行分析.
    是的,前三列输出的时三个线程各自的循环次数,main_counter输出的时总循环次数,sun输出各个线程循环次数的和.
    因为假设main_counter=0时,当线程1还没有完成加1操作的时候,main_counter还是为0此时线程2也开始执行main_counter++,两线程各执行一次加1操作,
    线程1将main_counter值变为1,线程2也将main_的值变为1,导致main_counter实际只加了1,比理论值偏小.
  3. thread_work()内是死循环,它是怎么退出的?你认为这样退出好吗?
    主进程return掉了,不好.

修改:将注释去掉即可.

3.互斥实验

#include 
#include 
#include 
#include 
#include 

#define LOOP_TIMES 10000

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

void *thread_worker(void *arg)
{
	int i;
	for(i=0;i<LOOP_TIMES;i++)
	{
		pthread_mutex_lock(&mutex2);
		pthread_mutex_lock(&mutex1);
		critical_section(2,i);
		pthread_mutex_unlock(&mutex1);
		pthread_mutex_unlock(&mutex2);
	}

	pthread_mutex_destory(&mutex1);
	pthread_mutex_destory(&mutex2);
	return 0;
}

void *critical_senction(int thread_num,int i)
{
	printf("Thread%d : %d\n",thread_num,i);
}

int main()
{
	int rtn,i;
	pthread_t pthread_id = 0; //存放子线程id
	rtn = pthread_create(&pthread_id,NULL,threadd_work,NULL);

	if(rtn != 0)
	{
		printf("pthread_create ERROR!\n");
		return -1;
	}

	for(i=0;i<LOOP_TIMES;i++)
	{
		pthread_mutex_lock(&mutex1);
		pthread_mutex_lock(&mutex2);
		critical_section(1,i);
		pthread_mutex_unlock(&mutex2);
		pthread_mutex_unlock(&mutex1);
	}

	pthread_mutex_destory(&mutex1);
	pthread_mutex_destory(&mutex2);
	return 0;
}

阅读程序,编译程序后,先预计一下这个程序的运行结果.
运行程序,若没有响应,按ctrl+c中断程序,然后再次运行,如此反复若干次,记录下每次的运行结果.
若产生了死锁,请修改程序,使其不会死锁.

-回答下列问题

  1. 你预想deadlock.c的运行结果会如何?
    有时会死锁
  2. deadlock.c的世界运行结果如何?多次运行每次的现象都一样吗?为什么会这样?
    基本都会死锁,因为循环次数很多,死锁的概率很大,但多次运行死锁的时间不同,因为死锁在哪个循环不同.
    关于死锁,博主以前的线程那篇有提到.

修改:

#include 
#include 
#include 
#include 
#include 

#define LOOP_TIMES 10000

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

void *thread_worker(void *arg)
{
	int i;
	for(i=0;i<LOOP_TIMES;i++)
	{
		pthread_mutex_lock(&mutex2);
		pthread_mutex_lock(&mutex1);
		critical_section(2,i);
		pthread_mutex_unlock(&mutex1);
		pthread_mutex_unlock(&mutex2);
	}

	pthread_mutex_destory(&mutex1);
	pthread_mutex_destory(&mutex2);
	return 0;
}

void *critical_senction(int thread_num,int i)
{
	printf("Thread%d : %d\n",thread_num,i);
}

int main()
{
	int rtn,i;
	pthread_t pthread_id = 0; //存放子线程id
	rtn = pthread_create(&pthread_id,NULL,threadd_work,NULL);

	if(rtn != 0)
	{
		printf("pthread_create ERROR!\n");
		return -1;
	}

	for(i=0;i<LOOP_TIMES;i++)
	{
		pthread_mutex_lock(&mutex2);
		pthread_mutex_lock(&mutex1);
		critical_section(1,i);
		pthread_mutex_unlock(&mutex1);
		pthread_mutex_unlock(&mutex2);
	}

	pthread_mutex_destory(&mutex1);
	pthread_mutex_destory(&mutex2);
	return 0;
}

测验

1.哲学家就餐问题

#include 
#include 
#include 
#include 
#include 
#include 
#include 

pthread_mutex_t chopstick[6];

//获得该哲学家所要的筷子编号
void get(int *left,int *right,char phi)
{
    ......
}

void *eat_think(void *arg)
{
    char phi = *(char *)arg;
    int left,right;

    //得到筷子编号
    get(&left,&right,phi); 

    for(;;)
    {
        usleep(10);
        
        //为左边筷子加锁,表示该筷子已经被拿了
        pthread_mutex_lock(&chopstick[left]);
        printf("....");

        //为右边筷子加锁,如果该筷子已经加锁了,即被别人拿去了,那么该哲学家没有足够的筷子吃饭,放弃这次吃饭
        if(pthread_mutex_trylock(&chopstick[right]) == EBUSY)
        {
            //为左边筷子解锁,即放下左边筷子
            pthread_mutex_unlock(&chopstick[left]);
            continue;
        }

        //若该哲学家有足够的筷子,则他可以吃饭
        printf("....");
        printf("....");

        //吃饭时间
        usleep(10);

        //为左边筷子解锁,即放下锁边筷子
        pthread_mutex_unlock(&chopstick[left]);
        printf("....");

        //为右边筷子解锁,即放下右边筷子
        pthread_mutex_unlock(&chopstick[right]);
        printf("....");
    }
}

int main()
{
    pthread_t A,B,C,D,E; 

    int i;
    
    //初始化互斥锁
    for(i=0;i<5;i++) 
        pthread_mutex_init(&chopstick[i],NULL)
    
    //创建五个线程
    pthread_create(&A,NULL,eat_think,(void *)"A");
    pthread_create(&B,NULL,eat_think,(void *)"B");
    pthread_create(&C,NULL,eat_think,(void *)"C");
    pthread_create(&D,NULL,eat_think,(void *)"D");
    pthread_create(&E,NULL,eat_think,(void *)"E");

    pthread_join(A,NULL);
    pthread_join(B,NULL);
    pthread_join(C,NULL);
    pthread_join(D,NULL);
    pthread_join(E,NULL);
    return 0;
}

2.生产者,消费者模型

#include 
#include 
#include 
#include 
#include 
#include 

pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
pthread_cond_t cond;

int arg = 0;

void *st(void *arg)
{
    for(;;)
    {
        pthread_mutex_lock(&mutex1);
        arg++;

        if(arg > 0)
        {
            pthread_cond_signal(&cond);
        }
        pthread_mutex_unlock(&mutex1);
    }

}

void *sp(void *arg)
{
    for(;;)
    {
        pthread_mutex_lock(&mutex1);
        while(arg < 1)
        {
            pthread_cond_wait(&cond,&mutex1);
            pthread_mutex_lock(&mutex2);
            arg--;
            pthread_mutex_unlock(&mutex2);
        }
        pthread_mutex_unlock(&mutex1);
    }
}

int main()
{
    pthread_t x,y;
    pthread_mutex_init(&mutex,NULL);
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond);

    pthread_create(&x,NULL,(void *)x,NULL);
    pthread_create(&y,NULL,(void *)y,NULL);

    pthread_join(x,NULL);
    pthread_join(y,NULL);

    return 0;
}

你可能感兴趣的:(Linux)