Linux系统编程——线程

一.线程概述

1.1什么是线程,什么是进程,它们间的联系和区别?

  • 进程:进程是程序运行的实例,而程序只是指令,数据以及组织形式的描述。同时进程是分配资源的最小单位。
  • 线程:线程是程序执行的最小单位。
  • 联系:线程被包含在进程中。一个进程至少有一个线程,表示进程同时只做一件事。线程和进程所有的数据和信息都是共享的,共用一个地址空间。
  • 区别:进程拥有自己独立的地址空间,奔溃不会对其他进程产生影响。线程有自己的栈堆和局部变量,但依赖于所属进程的地址空间,线程死掉,整个进程都会死掉。所以多进程会比多进程健壮,但耗费资源较大且效率要差一些。

1.2为什么用线程?

  • 相对进程线程耗费资源少,比较节俭
  • 相对进程线程之间共享数据空间,所以具有方便的通信机制
  • 提高应用程序响应速度
  • 在线程数量不多于cpu数量时,多cpu系统更加有效,不同线程运行在不同cpu上
  • 改善程序结构,利于程序的理解和修改

二.线程开发API(线程,互斥锁,条件:3+4+5)

2.1线程的创建,退出及等待

  • 创建:pthread_create()
#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

第一个参数pthread:一个整型指针,指向新建线程的ID
第二个参数attr:线程的属性,设为NULL,创建默认属性线程
第三个参数start_toutine():执行线程任务的函数,线程从函数的地址开始执行,
第四个参数:指针,指向存放函数参数的结构

  • 退出:pthread_exit()
       #include <pthread.h>

       void pthread_exit(void *retval);
  • 等待:pthread_join()
       #include <pthread.h>

       int pthread_join(pthread_t thread, void **retval);

  • 实例:
#include<stdio.h>
#include <pthread.h>

void *func(void *arg){

	static char *retval = "this is retval of  pthread_join";

	printf("t1:pthread_self = %ld\n ",(unsigned long)pthread_self());
	printf("t1:parama = %s\n",(char *)arg);

	pthread_exit((void *)retval);

}




int main(){

	int ret;

	char *parama ="this is a test" ;

	char *retval = NULL;

	pthread_t t1;

	ret = pthread_create(&t1,NULL,func,(void*)parama);
	if(ret == 0){
	
		printf("main:create pthread success\n");
		printf("main:pthread_self = %ld\n ",(unsigned long)pthread_self());
	}

	pthread_join(t1,(void **)&retval);
	printf("retval = %s\n",retval);

	return 0;

}

2.2互斥锁

  • 互斥锁的意义在于,同一时间只允许一个线程运行和访问共享资源,防止出现数据不一致的问题。
  • 互斥锁相关API:
  1. 创建及销毁互斥锁
       #include <pthread.h>

       int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
       //成功返回0,失败返回错误编码
  1. 加锁,解锁
       #include <pthread.h>

       int pthread_mutex_lock(pthread_mutex_t *mutex);
       int pthread_mutex_trylock(pthread_mutex_t *mutex);
       int pthread_mutex_unlock(pthread_mutex_t *mutex);
  1. 例子:
#include<stdio.h>
#include <pthread.h>
#include<unistd.h>
#include <stdlib.h>


pthread_mutex_t mutex;

void *func1(void *arg){

		pthread_mutex_lock(&mutex);
		printf("t1\n");
		printf("t1\n");
		pthread_mutex_unlock(&mutex);

}


void *func2(void *arg){

                pthread_mutex_lock(&mutex);
                printf("t2t2\n");
				printf("t2t2\n");
                pthread_mutex_unlock(&mutex);
		
}


void *func3(void *arg){

                pthread_mutex_lock(&mutex);
                printf("t3t3t3\n");
				printf("t3t3t3\n");
                pthread_mutex_unlock(&mutex);

}




int main(){

	int ret1;
	int ret2;
	int ret3;

	pthread_t t1;
	pthread_t t2;
	pthread_t t3;

	int parama =100;

	pthread_mutex_init(&mutex,NULL);

	ret1 = pthread_create(&t1,NULL,func1,(void*)&parama);
	if(ret1 != 0){
		
		printf("creat t1 fail\n");
		exit(-1);
	}


        ret2 = pthread_create(&t2,NULL,func2,(void*)&parama);
        if(ret2 != 0){

                printf("creat t2 fail\n");
                exit(-1);
        }


        ret3 = pthread_create(&t3,NULL,func3,(void*)&parama);
        if(ret3 != 0){

                printf("creat t3 fail\n");
                exit(-1);
        }

	pthread_join(t1,NULL);
	pthread_join(t2,NULL);
	pthread_join(t3,NULL);


	pthread_mutex_destroy(&mutex);	

	return 0;

}

2.3 死锁

  • 当前线程的锁(资源)被其它线程占用且得不到释放,导致当前线程被一直锁住。
  • 例如,t1把t2需要的锁先拿到了,t2则先把t1需要的锁拿到了,导致t1,t2相互锁死:
#include<stdio.h>
#include <pthread.h>
#include<unistd.h>
#include <stdlib.h>

pthread_mutex_t mutex1;
pthread_mutex_t mutex2;

void *func1(void *arg){

		pthread_mutex_lock(&mutex2);
		sleep(1);
	
		pthread_mutex_lock(&mutex1);
		printf("t1\n");
		printf("t1\n");
		pthread_mutex_unlock(&mutex1);

}


void *func2(void *arg){
		
		pthread_mutex_lock(&mutex1);
		sleep(1);		

                pthread_mutex_lock(&mutex2);
                printf("t2t2\n");
				printf("t2t2\n");
                pthread_mutex_unlock(&mutex2);
		
}


int main(){

	int ret1;
	int ret2;

	pthread_t t1;
	pthread_t t2;

	int parama =100;

	pthread_mutex_init(&mutex1,NULL);
	pthread_mutex_init(&mutex2,NULL);

	ret1 = pthread_create(&t1,NULL,func1,(void*)&parama);
	if(ret1 != 0){
		
		printf("creat t1 fail\n");
		exit(-1);
	}


        ret2 = pthread_create(&t2,NULL,func2,(void*)&parama);
        if(ret2 != 0){

                printf("creat t2 fail\n");
                exit(-1);
        }



	pthread_join(t1,NULL);
	pthread_join(t2,NULL);


	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);	

	return 0;

}

2.4条件锁

  • 互斥锁规定同一时间,最多允许多少个线程运行;而条件锁则保证同一时间这些线程运行的顺序,条件锁可以和互斥锁配合使用。

  • 创建和销毁

       #include <pthread.h>

       int pthread_cond_destroy(pthread_cond_t *cond);
       int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

  1. 触发和广播
       #include <pthread.h>

       int pthread_cond_broadcast(pthread_cond_t *cond);
       int pthread_cond_signal(pthread_cond_t *cond);
  1. 等待
       #include <pthread.h>

       int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,
       const struct timespec *restrict abstime);
       int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
  • 实战(验证线程和进程共享内存空间)
#include<stdio.h>
#include <pthread.h>
#include<unistd.h>
#include <stdlib.h>

pthread_cond_t cond1;
pthread_cond_t cond2;
pthread_mutex_t mutex;

int data = 1;
int cnt = 1;

void *func1(void *arg){

	pthread_mutex_lock(&mutex);

	while(1){

		if(cnt <= 3){

			printf("t1:data = %d \n",data);
			data++;
			sleep(1);
			cnt++;
		}else{
			
			cnt = 1;//计数重置
			pthread_cond_signal(&cond1);//发送信号给,解锁t2
			pthread_cond_wait(&cond2,&mutex);//等待t2		
		}
	
	}

	pthread_mutex_unlock(&mutex);
}


void *func2(void *arg){

	pthread_mutex_lock(&mutex);
	
	while(1){
		if(data == 1){
		
			pthread_cond_wait(&cond1,&mutex);//第一次,让t2等t1,保证t1先运行
		}
	
		if(cnt <= 3){//每个线程打印三次

              		 printf("t2:data = %d \n",data);
			 data++;
			 sleep(1);
			 cnt++;
		}else {

                        cnt = 1;//达到三次,计数重置
                        pthread_cond_signal(&cond2);//发送信号,解锁t1
			pthread_cond_wait(&cond1,&mutex);//等待t1
					
		}

	}

	pthread_mutex_unlock(&mutex);	
}


int main(){

	int ret1;
	int ret2;

	pthread_t t1;
       	pthread_t t2;	

	int parama =100;

	pthread_cond_init(&cond1,NULL);
	pthread_cond_init(&cond2,NULL);
	pthread_mutex_init(&mutex,NULL);

	ret1 = pthread_create(&t1,NULL,func1,(void*)&parama);
	if(ret1 != 0){
		
		printf("creat t1 fail\n");
		exit(-1);
	}


        ret2 = pthread_create(&t2,NULL,func2,(void*)&parama);
        if(ret2 != 0){

                printf("creat t2 fail\n");
                exit(-1);
        }




	pthread_join(t1,NULL);
	pthread_join(t1,NULL);

	pthread_cond_destroy(&cond1);
	pthread_cond_destroy(&cond2);
	pthread_mutex_destroy(&mutex);

	return 0;

}
ztj@ubuntu:~/part2/PTHREAD$ ./a.out
t1:data = 1 
t1:data = 2 
t1:data = 3 
t2:data = 4 
t2:data = 5 
t2:data = 6 
t1:data = 7 
t1:data = 8 
t1:data = 9 
t2:data = 10 
t2:data = 11 
t2:data = 12 
t1:data = 13 
t1:data = 14 
t1:data = 15 
t2:data = 16 
t2:data = 17 
t2:data = 18 
t1:data = 19 
t1:data = 20 
t1:data = 21 
t2:data = 22 
t2:data = 23 
t2:data = 24 
t1:data = 25 
^C
ztj@ubuntu:~/part2/PTHREAD$ 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

elaot

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

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

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

打赏作者

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

抵扣说明:

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

余额充值