Bootstrap

【Linux系统软件编程】进程线程——线程

1、进程:程序动态执行的过程,包括创建、调度和消亡

2、线程:线程是一个轻量级的进程

3、进程空间包括:

  • 文本段、数据段、系统数据段

4、线程空间包括:

  • 1. 栈区独享、与进程共享文本段、数据段、堆区
  • 2. 线程位于进程空间内部

5、进程和线程的区别

  1. 进程是操作系统资源分配的最小单元:拥有独立的 文本段、数据段和系统数据段
  2. 线程是CPU任务调度的最小单元:只有栈区是独立的,其余都是共享的
  • 线程依附于进程存在

6、线程的创建

  1. 每个线程独立拥有8M(默认)栈空间
  2. 其余的文本段、数据段、堆区都是与进程及进程内的其余线程共享

7、线程的调度

  1. 线程的调度等价于进程的调度
  2. 线程是CPU任务调度的最小单元

8、线程的消亡

  1. 与进程消亡保持一致
  2. 僵尸线程:等到线程结束需要回收线程空间,否则会产生僵尸线程

9、多进程vs多线程

1.执行效率:多线程 > 多进程

  • 线程间的任务切换是再同一片进程内部空间完成任务切换,资源开销较小
  • 进程间的任务切换需要映射到不同的物理地址空间,频繁切换资源开销大

2.多任务间通信实现(易用性):多线程 > 多进程

  • 多线程拥有共享空间,通信更加方便
  • 多进程没有共享空间,需要更为复杂的方法实现多进程间通信

3.多任务间通信机制复杂程度:多进程 > 多线程

  • 多线程操作全局变量会引入资源竞争,需要加锁来解决
  • 多进程没有资源竞争

4.多任务间通信保证任务的安全性:多进程 > 多线程

  • 线程异常崩溃会导致进程崩溃,该进程中的其余线程异常结束
  • 进程异常结束,不会影响其余进程

5.综上所述:多进程和多线程实际效率:差不多(半斤八两)

  1. 一个软件内部不同任务 用多线程
  2. 不同软件 用多进程
  3. 简单来说,一个程序就是一个进程,这个程序内部的多个任务,用多线程
  4. 系统上面的多个任务,用多进程
  • 多线程像平面交通,造价成本低,也很方便,但互相之间有干扰(左转直行),所以需要红绿灯(锁的机制)
  • 多进程像立体交通,造价成本高,但是没有红绿灯

10、线程相关的函数接口

加头文件<pthread.h>

pthread是一个库,在编译是要加 -l

类比进程中的函数接口:

fork == pthread_create
exit == pthread_exit
wait == pthread_join

(1)pthread_create

    man 3 pthread_create

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

功能:
    在调用函数的进程中创建一个线程
参数:
    thread:存放线程ID空间的首地址
    attr:线程的属性
    start_routine:线程函数的入口
    arg:传入线程函数的参数
返回值:
    成功返回0
    失败返回错误数字

这里有一个比较难理解的小点:void *(*start_routine) (void *)是pthread_create需要的一个参数,这个参数是一个函数指针,这个函数指针,指向线程启动时要执行的函数。这个函数名为start_routine,括号前面的void *表示这个函数的返回值类型为void *型,括号后面的(void *)表示这个函数需要传入的参数类型是void *型。

简单来说:这是一个  void *型返回值,并且有一个void *型参数的 函数指针

(2)pthread_exit

    man 3 pthread_exit

void pthread_exit(void *retval);

功能:
    线程退出
参数:
    retval:线程退出的值
返回值:
    缺省

(3)pthread_join

    man 3 pthread_join

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

功能:
    回收线程空间
参数:
    thread:要回收的线程的ID
    retval:存放线程结束状态指针空间的首地址
返回值:
    成功返回0
    失败返回错误码
  • 注意:
  1. pthread_join具有阻塞功能,线程不结束,一直等到线程结束,回收到线程空间再继续向下执行
  2. pthread_join具有同步功能


练习1:pthread线程使用

#include <stdio.h>
#include "public.h"

void *thread_fun(void *arg)
{
	printf("线程(TID:%#x)开始执行\n", (unsigned int)pthread_self());

	return NULL;
}

int main(int argc, const char **argv)
{
	pthread_t tid;
	int ret = 0;

	ret = pthread_create(&tid, NULL, thread_fun, NULL);
	if (ret != 0)
	{
		ERR_MSG("fail to pthread_create");
		return -1;
	}

	while (1)
	{
		
	}

	return 0;
}

练习2:pthread线程创建(pro版)

 #if 0 和 #endif 中间的内容是基础版

#include <stdio.h>
#include "public.h"

void *thread1(void *arg)
{
	printf("线程1(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}

void *thread2(void *arg)
{
	printf("线程2(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}

void *thread3(void *arg)
{
	printf("线程3(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}

int main(int argc, const char **argv)
{
	pthread_t tid[3];
	int i = 0;
	void *(*pfun[3])(void *) = {thread1, thread2, thread3};

	for (i = 0; i < 3; i++)
	{
		pthread_create(&tid[i], NULL, pfun[i], NULL);
	}

	for (i = 0; i < 3; i++)
	{
		pthread_join(tid[i], NULL);
	}

#if 0
	pthread_t tid1;
	pthread_t tid2;
	pthread_t tid3;

	pthread_create(&tid1, NULL, thread1, NULL);
	pthread_create(&tid2, NULL, thread2, NULL);
	pthread_create(&tid3, NULL, thread3, NULL);

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
#endif

	return 0;
}

练习3:pthread线程创建(pro max版)使用函数指针数组

#include <stdio.h>
#include "public.h"

void *thread(void *arg)
{
	int num = (int)arg;

	printf("线程%d(TID:%#lx)正在执行\n", num, pthread_self());

	return NULL;
}

#if 0
void *thread1(void *arg)
{
	printf("线程1(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}

void *thread2(void *arg)
{
	printf("线程2(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}

void *thread3(void *arg)
{
	printf("线程3(TID:%#lx)正在执行\n", pthread_self());

	return NULL;
}
#endif

int main(int argc, const char **argv)
{
	pthread_t tid[3];
	int i = 0;
	int a[3] = {1, 2, 3};
//	void *(*pfun[3])(void *) = {thread1, thread2, thread3};

	for (i = 0; i < 3; i++)
	{
		pthread_create(&tid[i], NULL, thread, (void *)(i+1));
	}

	for (i = 0; i < 3; i++)
	{
		pthread_join(tid[i], NULL);
	}

#if 0
	pthread_t tid1;
	pthread_t tid2;
	pthread_t tid3;

	pthread_create(&tid1, NULL, thread1, NULL);
	pthread_create(&tid2, NULL, thread2, NULL);
	pthread_create(&tid3, NULL, thread3, NULL);

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
#endif

	return 0;
}

;