创建线程

pthread_self函数

获取线程ID。其作用对应进程中 getpid() 函数。

       pthread_t pthread_self(void);      返回值:成功:0;     失败:无!

       线程ID:pthread_t类型,本质:在Linux下为无符号整数(%lu),其他系统中可能是结构体实现

       线程ID是进程内部,识别标志。(两个进程间,线程ID允许相同)

       注意:不应使用全局变量 pthread_t tid,在子线程中通过pthread_create传出参数来获取线程ID,而应使用pthread_self。

pthread_create函数

创建一个新线程。             其作用,对应进程中fork() 函数。

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

       返回值:成功:0;     失败:错误号      -----Linux环境下,所有线程特点,失败均直接返回错误号。

参数:  

       pthread_t:当前Linux中可理解为:typedef  unsigned long int  pthread_t;

参数1:传出参数,保存系统为我们分配好的线程ID

       参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。

       参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。

       参数4:线程主函数执行期间所使用的参数。

在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。start_routine函数接收一个参数,是通过pthread_create的arg参数传递给它的,该参数的类型为void *,这个指针按什么类型解释由调用者自己定义。start_routine的返回值类型也是void *,这个指针的含义同样由调用者自己定义。start_routine返回时,这个线程就退出了,其它线程可以调用pthread_join得到start_routine的返回值,类似于父进程调用wait(2)得到子进程的退出状态,稍后详细介绍pthread_join。

pthread_create成功返回后,新创建的线程的id被填写到thread参数所指向的内存单元。我们知道进程id的类型是pid_t,每个进程的id在整个系统中是唯一的,调用getpid(2)可以获得当前进程的id,是一个正整数值。线程id的类型是thread_t,它只在当前进程中保证是唯一的,在不同的系统中thread_t这个类型有不同的实现,它可能是一个整数值,也可能是一个结构体,也可能是一个地址,所以不能简单地当成整数用printf打印,调用pthread_self(3)可以获得当前线程的id。

attr参数表示线程属性,本节不深入讨论线程属性,所有代码例子都传NULL给attr参数,表示线程属性取缺省值,感兴趣的读者可以参考APUE。

【练习】:创建一个新线程,打印线程ID。注意:链接线程库 -lpthread                                            【pthrd_crt.c】

由于pthread_create的错误码不保存在errno中,因此不能直接用perror(3)打印错误信息,可以先用strerror(3)把错误码转换成错误信息再打印。如果任意一个线程调用了exit或_exit,则整个进程的所有线程都终止,由于从main函数return也相当于调用exit,为了防止新创建的线程还没有得到执行就终止,我们在main函数return之前延时1秒,这只是一种权宜之计,即使主线程等待1秒,内核也不一定会调度新创建的线程执行,下一节我们会看到更好的办法。

【练习】:循环创建多个线程,每个线程打印自己是第几个被创建的线程。(类似于进程循环创建子进程)                                                                                                                                                          【more_pthrd.c】

拓展思考:将pthread_create函数参4修改为(void *)&i, 将线程主函数内改为 i=*((int *)arg) 是否可以?

/***
pthread_create.c
***/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
void *thrd_func(void *arg)
{printf("In thread : thread id = %lu,pid = %u\n",pthread_self(),getpid());return NULL;}int main()
{pthread_t tid;int ret;printf("In main 1 : thread id = %lu,pid = %ui\n",pthread_self(),getpid());ret = pthread_create(&tid,NULL,thrd_func,NULL);if(0 != ret){fprintf(stderr,"pthread_create error:%s\n",strerror(ret));exit(1);    }sleep(1);printf("In main 2 : thread id = %lu,pid = %u\n",pthread_self(),getpid());return 0;
}

运行结果:

ubuntu1604@ubuntu:~/wangqinghe/linux/20190814$ ./pthread_create

In main 1 : thread id = 140573795596032,pid = 3648i

In thread : thread id = 140573787256576,pid = 3648

In main 2 : thread id = 140573795596032,pid = 3648

 

循环创建多个子线程
/***
mul_pthread.c
***/
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>void *thrd_func(void *arg)
{int i = (int)arg;sleep(i);printf("%dth thread: thread id = %lu,pid = %u\n",i+1,pthread_self(),getpid());return NULL;
}int main()
{pthread_t tid;int ret,i;for(i = 0; i < 5; i++){ret = pthread_create(&tid,NULL,thrd_func,(void *)i);if(0 != ret){fprintf(stderr,"pthrea_create error:%s\n",strerror(ret));exit(1);}}sleep(i);return 0;
}

运行结果:

ubuntu1604@ubuntu:~/wangqinghe/linux/20190814$ ./mul_pthread

1th thread: thread id = 140132717160192,pid = 4026

2th thread: thread id = 140132708767488,pid = 4026

3th thread: thread id = 140132700374784,pid = 4026

4th thread: thread id = 140132691982080,pid = 4026

5th thread: thread id = 140132683589376,pid = 4026

 

转载于:https://www.cnblogs.com/wanghao-boke/p/11376360.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++头文件

C/C头文件一览C、传统 C#include <assert.h> //设定插入点#include <ctype.h> //字符处理#include <errno.h> //定义错误码#include <float.h> //浮点数处理#include <fstream.h> //文件输入&#xff0f;输出#include <iomanip.h> //参数化…

Python变量类型

变量存储在内存中的值&#xff0c;这就意味着在创建变量时会在内存开辟一个空间。 基于变量的数据类型&#xff0c;解析器会分配指定内存&#xff0c;并决定什么数据可以被存储在内存中。 因此变量可以指定不同的数据类型&#xff0c;这些变量可以存储整数、小数、或字符。 变量…

线程退出

pthread_exit函数 将单个线程退出 void pthread_exit(void *retval); 参数&#xff1a;retval表示线程退出状态&#xff0c;通常传NULL 思考&#xff1a;使用exit将指定线程退出&#xff0c;可以吗&#xff1f; …

线程分离

pthread_detach函数 实现线程分离 int pthread_detach(pthread_t thread); 成功&#xff1a;0&#xff1b;失败&#xff1a;错误号 线程分离状态&#xff1a;指定该状态&#xff0c;线程主动与主控线程断开关系。线程结束后&#xff0c;其退出状态不由其他线程获取&#x…

线程知识点

控制原语对比 进程 线程 fork pthread_create exit pthread_exit wait pthread_join kill pthread_cancel getpid pthread_self 命名空间 线程属性 本节作为指引性介绍&…

读写锁

读写锁 与互斥量类似&#xff0c;但读写锁允许更高的并行性。其特性为&#xff1a;写独占&#xff0c;读共享。 读写锁状态&#xff1a; 一把读写锁具备三种状态&#xff1a; 1. 读模式下加锁状态 (读锁) 2. 写模式下加锁状态 (写锁) 3. 不加锁状态 读写锁特性&#xff1a; 读…

条件变量

条件变量&#xff1a; 条件变量本身不是锁&#xff01;但它也可以造成线程阻塞。通常与互斥锁配合使用。给多线程提供一个会合的场所。 主要应用函数&#xff1a; pthread_cond_init函数 pthread_cond_destroy函数 pthread_cond_wait函数 pthread_cond_timedwait函数 pthread_c…

文件锁

借助 fcntl函数来实现锁机制。 操作文件的进程没有获得锁时&#xff0c;可以打开&#xff0c;但无法执行read、write操作。 fcntl函数&#xff1a; 获取、设置文件访问控制属性。 int fcntl(int fd, int cmd, ... /* arg */ ); 参2&#xff1a; F_SETLK (struct flock *) 设置…

进程间同步

互斥量mutex 进程间也可以使用互斥锁&#xff0c;来达到同步的目的。但应在pthread_mutex_init初始化之前&#xff0c;修改其属性为进程间共享。mutex的属性修改函数主要有以下几个。 主要应用函数&#xff1a; pthread_mutexattr_t mattr 类型&#xff1a; 用于定义…

Python3字符串

字符串是Python中最常用的数据类型&#xff0c;可以使用单引号或双引号来创建字符串 创建字符串很简单&#xff0c;为变量分配一个值即可。 val1 ‘hello world’ var2 “Runoob” Python访问字符串的值 Python不支持单字符类型&#xff0c;单字符在Python中也是作为 一个字符…

服务器客户端编程

server 下面通过最简单的客户端/服务器程序的实例来学习socket API。 server.c的作用是从客户端读字符&#xff0c;然后将每个字符转换为大写并回送给客户端。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #incl…

Python3元组

Python的元组与列表相似&#xff0c;不同之处在于元组的元素不能修改 元组使用小括号&#xff0c;列表使用方括号 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可。 创建空元组 tup1 (); tup2 (1,) 元组只包含一个元素时&#xff0c;需要在…

Python3字典

字典是另一种可变容器模型&#xff0c;可存储任意类型的对象。 字典的每个键值(key>value)对用冒号分隔&#xff0c;每个对之间用逗号分隔&#xff0c;整个字典包括在花括号里&#xff0c;格式如下 d {key1 : value,key2 : value2} 键必须是唯一&#xff0c;但值则不必。 值…

线程回收

pthread_join函数 阻塞等待线程退出&#xff0c;获取线程退出状态 其作用&#xff0c;对应进程中 waitpid() 函数。 int pthread_join(pthread_t thread, void **retval); 成功&#xff1a;0&#xff1b;失败&#xff1a;错误号 参数&#xff1a;thread&#xff1a;线…

Python3数字

Python3数字数据类型用于存储数值。 数据类型是不允许改变的&#xff0c;这就意味着&#xff0c;如果改变数字数据类型的值&#xff0c;将重新分配内存空间。 Python支持三种不同不同的数值类型&#xff1a; 整型&#xff08;int&#xff09;&#xff1a;通常是被称为整型或整数…

多进程服务器

注意&#xff1a;包含了“wrap.c” 和“wrap.h”文件在上篇博客中 /*** server.c ***/ #include<stdio.h> #include<string.h> #include<netinet/in.h> #include<arpa/inet.h> #include<signal.h> #include<sys/wait.h> #include<ctype…

服务器之select

select select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024&#xff0c;单纯改变进程打开的文件描述符个数并不能改变select监听文件个数解决1024以下客户端时使用select是很合适的&#xff0c;但如果链接客户端过多&#xff0c;select采用的是轮询模型&#xff0c;会大…

服务器之poll

poll服务器方法采用将监听端口用数组存放起来&#xff0c;这样就不需要轮询的监听整个文件描述符了 #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);struct pollfd {int fd; /* 文件描述符 */short events; /* 监控的事件 */short revents; …

Mysql数据库简单使用(二)

Mysql导入.sql文件 进入数据库&#xff08;要导入的数据库&#xff09;数据库中有要导入.sql文件名的数据库&#xff0c;没有则新建。source 路径文件名souce /home/robot/csql.sql 数据库文件.sql文件放在/home/robot目录下 按照时间删除数据库数据 DELETE FROM 表名 WHERE 时…

Python3集合

集合&#xff08;set&#xff09;是一个无序的不重复元素序列。 可以使用大括号{ } 或set&#xff08;&#xff09;函数来创建集合&#xff0c;注意&#xff1a;创建一个空集合必须用set(),{ }是用来创建一个空字典的。 创建格式&#xff1a; param {value01,value02,…} set(…