多线程打印
迪丽瓦拉
2024-02-23 04:00:59
0

1)题目要求

多线程打印

Main 线程创建两个子线程 A 和 B,子线程 A 循环 3 次,每次 sleep 一秒后打印一行十个 A 字符;

int i;for (i = 0; i < 3; i++) {sleep(1);printf("AAAAAAAAAA\n");}

子线程 B 也是循环 3 次,每次 sleep 一秒后打印一行十个 B 字符。

多次执行程序,看看屏幕输出是什么情况。

相关知识:

与进程相关知识做对比,线程的api接口介绍如下:

进程

线程

注释

pid

pthread_t

  1. 线程ID,进程ID在整个系统中是唯一的(非负整数),但线程ID不同,线程ID只在它所属的进程环境中有效
  2. pthread_t从可移植的角度来讲,其定义是一个结构,不要简单地将其看做一个整数,如果要比较,需要有专门的函数pthread_equal
  3. 如何打印pthread_t: 考虑到可移植性,这个数据结构在不同的OS上实现是不同的,所以没有一个简单的统一打印方式。(网上有一个就是直接打印结构的二进制buffer,但没有必要),如果确定在Linux上可以查看Linux的实现方式决定打印方式。

/* Thread identifiers.  The structure of the attribute type is not exposed on purpose.  */

typedef unsigned long int pthread_t;

所以就Linux来说,可以直接打印%lu

getpid

pthread_self

获取自身的线程ID

fork

int

pthread_create(

pthread_t *thread,

const pthread_attr_t *attr,

void * (* routine)(void *),

void *arg

)

  1. 形参:
  • thread:指向pthread_t类型的指针,该地址将存放线程创建成功之后的线程TID。
  • attr:用户设置线程的属性,一般都不需要特殊设置,所以可简单设置为NULL。
  • *(*start_routine)(void *):传递新线程所要执行的函数的地址。注意:我们可以看到,如果想启动一个线程,就必须让这个线程关联一个子函数。我们一般称此函数为线程函数,
  • arg:新线程所有执行的函数的参数,标准线程创建接口只留了 一个参数传递。思考?如果想给线程函数传递多个参数,该怎么解决呢?A:如果需要传递的参数不止一个,那么需要把参数放到一个结构里
  1. 返回值由函数直接返回,不像其他POSIX函数设置errno。

1)线程的create涉及的入参

2)-lpthread  

exit

int  pthread_exit(void *value_ptr)

在不终止整个进程的情况下,单个线程可以有三种方式停止其工作流并退出:

  1. 线程从其工作函数中返回,返回值是线程的退出码
  2. 线程可以被同一进程中的其他线程取消
  3. 线程自己调用pthread_exit

注意:返回value_ptr时不能将该指针指向线程工作函数内的局部变量的地址,思考?局部变量存在在栈上,线程函数退出后,这个局部变量无效了,有可能在join时得到的会是无效值。所以如果要传一个结构,最好定义在堆上或者使用全局变量。

void *workfunc(void *arg) {

 int local = 0;

 pthread_exit(&local); // danger!

}

waitpid

int  pthread_join(pthread_t thread,  void **value_ptr)

一般此函数用在主线程中,等待通过thread指定的线程终止,此函数调用成功,可以通过value_ptr获取终止线程的返回值。

注意:如果等待的线程没有终止,此函数将引起调用者阻塞。成功返回0,失败返回-1。

线程执行完后如果不join的话,线程的资源会一直得不到释放而导致内存泄漏!所以需要join或者detach,本课程不讲detach,有兴趣学生自己回去看

abort

int  pthread_cancel(pthread_t thead)

线程通过调用pthread_cancel来请求取消同一个进程中的其他线程。pthread_cancel并不等待线程终止,仅提出请求。

审核要求:

1. 提交全部程序代码,代码思路规范清晰,命名规范。

2. 运行能直接输出所要求的结果。

2)实现过程

#include 
#include 
void *funa(void *arg)
{	int i;for(i=0;i<3;i++){sleep(1);printf("AAAAAAAAAA\n");}pthread_exit(NULL);
}void *funb(void *arg)
{int i;for(i=0;i<3;i++){sleep(1);printf("BBBBBBBBBB\n");}pthread_exit(NULL);
}int main()
{	pthread_t ta,tb;if(0!=pthread_create(&ta,NULL,funa,NULL))
{perror("pthread error!");exit(0);
}if(0!=pthread_create(&tb,NULL,funb,NULL))
{perror("pthread error!");exit(0);
}if(0!=pthread_join(ta,NULL))
{perror("join error\n");exit(0);
}if(0!=pthread_join(tb,NULL))
{perror("join error\n");exit(0);
}return 0;
}

相关内容