linux多线程编程-学习笔记

linux多线程编程

  • 进程与线程之前的区别
    • 进程
    • 线程
    • 线程的特点
  • 线程共享资源
    • 一个进程中多个线程可以共享一下资源
    • 每个线程私有的资源包括
  • linux线程编程
    • pthread 线程库中提供了如下基本操作
    • 线程示例
    • 同步和互斥机制
  • 线程间通讯
    • 同步
    • 信号量(灯)
      • 信号量-P/V操作
      • 信号量的种类
      • pthread库常用的信号量操作函数
    • 线程同步-示例1
  • 参考资料

进程与线程之前的区别

进程

  1. 在linux中,资源的分配是以进程为单位的;
  2. 进程有独立的地址空间;
  3. linux为每个进程创建task_struct;
  4. 每个进程都参与内核调度,互不影响;

线程

  1. 进程在切换时开销比较大
  2. 很多操作系统引入了轻量级进程LWP(也就是线程)
  3. 同一进程中的线程共享相同的地址空间

线程的特点

  1. 共享相同的地址空间
  2. 使用多线程的好处:大大提高了任务切换的效率;避免额外的TLB&cache的刷新;

线程共享资源

一个进程中多个线程可以共享一下资源

  1. 可执行的指令;
  2. 静态数据
  3. 进程中打开文件描述符;
  4. 当前工作目录;
  5. 用户ID;
  6. 用户组ID;

每个线程私有的资源包括

  1. 线程ID(TID);
  2. PC(程序包计数器)和相关寄存器;
  3. 堆栈;
  4. 错误号;
  5. 优先级;
  6. 执行状态和属性;

linux线程编程

pthread 线程库中提供了如下基本操作

  1. 创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,
					void *(*routine)(void *),void *arg);
//成功返回0,失败返回错误代码
//thread线程对象
//attr线程属性,NULL代表默认属性
//routine线程执行的函数
//arc传递给routine的参数
  1. 回收线程
#include <pthread.h>
int pthread_join(pthread_t thread,void **retval);
//成返回0,失败返回错误代码
//thread要回收的线程对象
//调用线程阻塞知道thread结束
//*retval接收线程thread的返回值
  1. 结束线程
#include <pthread.h>
void pthread_exit(void *retval);
//结束当前线程
//retval可被其他线程通过pthread_join获取
//线程私有资源被释放

线程示例

char message[32]="hello world";
void *thread_func(void *arg);

int main(int argc,char *argv[])//主线程
{
	pthread_t a_thread;
	void *result;
	if(pthread_create(&a_thread,NULL,thread_func,NULL) != 0){
		printf("fail to pthread_create\n");
		exit(-1);
	}
	pthread_join(&a_thread,&result);
	printf("result is %s\n",result);
	printf("message is %s\n",message);
	return 0;	
}


void *thread_func(void *arg){//子线程
	sleep(1);
	strcpy(message,"marked by thread");
	pthread_exit("thank you for waiting for me");
}

同步和互斥机制

  1. 信号量
  2. 互斥锁

线程间通讯

线程共享同一进程的地址空间
优点:线程间通讯很容易,通过全局变量交换数据
缺点多个线程访问共享数据需要同步或者互斥机制

同步

概念:同步是指对个任务按照约定的先后次序,相互配合完成一件事。
基于信号量的概念提出的一种同步机制。由信号量来决定线程是继续运行还是阻塞等待

信号量(灯)

  1. 信号量代表某一类资源,,其值表示系统中该资源的数量;
  2. 信号量是受保护的,只有通过初始化、P操作(申请资源)、V操作(释放资源)

信号量-P/V操作

P(S)含义:

if(信号量的值大于0){
	申请资源;
	信号量的值减1}else{
	申请资源的任务阻塞等待;
}

V(S)含义:

信号量值加1if(有任务在等待资源){
	唤醒等待的任务,继续运行;
}

信号量的种类

  1. 无名信号量(基于内存的信号量)
  2. 有名信号量

pthread库常用的信号量操作函数

  1. sem_init
#include 
int sem_init(sem_t *sem,int pshared,unsigned int value);
//成功时放回0,失败返回EOF
//sem指向要初始化的信号量对象
//pshare  0:线程间   1:进程间
//信号初值
  1. P/V操作
#include 

int sem_wait(sem_t *sem);//P操作
int sem_post(sem_t *sem);//V操作
//成时返回0,失败返回EOF
//指向要操作的信号量对象

线程同步-示例1

两个线程同步读写缓冲区(生成者/消费者问题)

char buf[32];
sem_t sem;//信号量对象
void *function(void *arc);

int main(int argc,char *argv[]){
	pthread_t a_thread;
	
	if(sem_init(sem,0,0) < 0){
		perror("sem_init");
		exit(-1);
	}
	if(pthread_create(&a_thread,NULL,function,NULL) != 0){
	printf("fail pthread_create");
	exit(-1);
	}
}

参考资料

链接: https://www.bilibili.com/video/BV1Fs411M7d5?share_source=copy_web.

你可能感兴趣的:(多线程,linux)