参考资料:

1.博客1:https://blog.csdn.net/zhou1021jian/article/details/71531699

2.博客2:https://blog.csdn.net/weixin_40039738/article/details/81145247

本文主要介绍下面函数的用法和代码示例

pthread_create            创建线程
pthread_exit            终止线程
pthread_join            回收进程
pthread_detach          线程分离
pthread_attr_setdetachstate   设置线程属性

注意:在linux下查看线程相关的方法时,man 出来可以非常多,所以要想查阅资料搞清楚到底需要啥

pthread_create 创建线程

函数原型:

#include <pthread.h>

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

创建出的新线程退出的可能情况:

* It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).

* It returns from start_routine().  This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.

* It is canceled (see pthread_cancel(3)).

* Any of the threads in the process calls exit(3), or the main thread performs a return from main().  

简言之就是以下几种可能:
1.执行新线程的函数“走完了”;
2.新线程本身或者与之join的线程执行“终止线程”的方法pthread_exit;
3.取消创建该线程pthread_cancel;
4.其他线程执行推出exit,或者主线程return弹(函数)栈

pthread_exit 终止进程

终止调用它的线程并返回一个指向某个对象的指针。

创建进程 代码示例:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h> void* thr(void* arg) {
printf("i am a thread! pid = %d, tid = %ld\n", getpid(), pthread_self());
//pthread_exit((void*)100);
// return nullptr;
} int main(int argc, char* argv[]) {
/*
* int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
*/ pthread_t tid { 0 };
pthread_create(&tid, nullptr, thr, nullptr);
printf("i am a main thread! pid = %d, tid = %ld\n", getpid(), pthread_self()); //sleep(1);
/*1. 如果添加pthread_exit()在主线程,则主线程马上退出,不在执行主线程下面的程序,但是主线程中启动的其他线程继续执行,程序不会马上退出,等待子线程执行完毕退出。
2. 如果不添加,主线程不等待子线程执行完毕,程序直接退出,子线程可能没有执行完毕。*/
pthread_exit(nullptr); //return 0;// no use, never exec
}

线程joinable

上面的代码中子线程创建成功依赖于,主线程要么是推出的很慢(有耗时操作)来保证一定会创建子线程,要么是加上pthread_exit,我们往往不想这么做,因此介绍
pthread_join  

pthread_join

函数原型:

#include <pthread.h>

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

描述:

The  pthread_join() function  waits for the thread specified by thread to terminate. wait()方法用来回收进程,是阻塞的,类比,pthread_join也是阻塞的,直至指定的进程终止才会执行后面的代码。

If that thread has already terminated, then pthread_join() returns immediately.  

The thread specified by thread must be joinable.

代码示例:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h> void* thr(void* arg) {
printf("i am a thread! pid = %d, tid = %ld\n", getpid(), pthread_self());
sleep(3);
pthread_exit((void*)1004);
// return (void*)100;
} int main(int argc, char* argv[]) {
/*
* int pthread_join(pthread_t thread, void **retval);
*/
pthread_t tid { 0 };
pthread_create(&tid, nullptr, thr, nullptr);
printf("i am a main thread! pid = %d, tid = %ld\n", getpid(), pthread_self()); void* ret = nullptr;
pthread_join(tid, &ret);//回收子线程,pthread_join会阻塞,直到子线程退出
printf("ret exit with %ld\n", (long)ret); //sleep(1);
/*
* 此处主线程加pthread_exit仅用来回收主线程,不影响子线程创建,因为pthread_join的作用*/
pthread_exit(nullptr); //return 0; no use there
}

线程detached

线程默认属性就是joinable,依赖于创建该线程的“父线程”(其实线程之间不存在父子关系),但是可以修改线程属性。

修改方法有两种,1是使用函数pthread_detach,2是设置属性pthread_attr_setdetachstate。

当线程被分离(detached)后,这个线程的回收就交给操作系统,就不是用户可以控制的了。

pthread_detach

函数原型:

#include <pthread.h>

int pthread_detach(pthread_t thread);

描述:

The  pthread_detach()  function  marks the thread identified by thread as detached.  

When a detached thread terminates, its resources are automatically released back to the system without the

need for another thread to join with the terminated thread.

pthread_attr_setdetachstate

函数原型:

#include <pthread.h>

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

描述:

The  pthread_attr_setdetachstate()  function  sets  the  detach  state  attribute  of the thread attributes object referred to by attr to the value specified in detachstate.  

The detach state attribute determines whether a thread created using the thread attributes object attr will be created in a joinable or a detached state.

The following values may be specified in detachstate: PTHREAD_CREATE_DETACHED
Threads that are created using attr will be created in a detached state. PTHREAD_CREATE_JOINABLE
Threads that are created using attr will be created in a joinable state. The default setting of the detach state attribute in a newly initialized thread attributes object is PTHREAD_CREATE_JOINABLE.(默认是joinable,可以设置为detached) The pthread_attr_getdetachstate() returns the detach state attribute of the thread attributes object attr in the buffer pointed to by detachstate.

代码示例:

#include <stdio.h>
#include <pthread.h>
#include <string.h> void * thr(void * arg) {
printf("i am child thread \n");
return nullptr;
} int main(int argc, char* argv[]) { pthread_attr_t attr;
pthread_attr_init(&attr);
/*
* 当设置为PTHREAD_CREATE_JOINABLE时,下面可以用pthread_join回收,但是如果设置为PTHREAD_CREATE_DETACHED则不可以
* */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t tid {0};
pthread_create(&tid, &attr, thr, nullptr); int ret = 0;
if ((ret = pthread_join(tid, nullptr)) > 0) {
//printf("join err:%ld, %s\n", (long)ret, strerror((long)ret));
printf("join err:%d, %s\n", ret, strerror(ret));
} pthread_attr_destroy(&attr); return 0;
}

其他代码:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h> void * thr(void * arg) { // malloc();
printf("i am child thread, tid = %ld, arg = %ld\n", pthread_self(), (long)arg);
//return nullptr;
return (void *)(100 + (long)arg);
} int main(int argc, char* argv[]) { pthread_t tid[5]; int length = sizeof(tid) / sizeof(pthread_t); printf("**********************length = %d\n", length); for (long i = 0; i < length; ++i) {
/* (void*)i :
* 这里不能这样写,最好是先在堆区创建,再传进去,用完了在外面释放,这样保证数据没问题。
* 如果直接传地址,可能在创建子线程的过程中,数据发生了变化(指向的地址也变了),这样传参不稳定,有问题。
* */
pthread_create(&tid[i], nullptr, thr, (void*)i);
} for (int i = 0; i < length; ++i) {
void* ret = nullptr;
pthread_join(tid[i], &ret);
printf("i == %d, ret == %ld\n", i, (long)ret);
} return 0;
}

linux多进/线程编程(7)——多线程1(线程的创建,回收,分离,设置线程属性等)的更多相关文章

  1. 用委托在listbox中异步显示信息,解决线程间操作无效,从不是创建控件的线程访问它

    //创建一个委托,是为访问listbox控件服务的. public delegate void UpdateTxt(string msg); //定义一个委托变量 public UpdateTxt u ...

  2. [Winform]线程间操作无效,从不是创建控件的线程访问它的几个解决方案,async和await?

    目录 概述 取消跨线程检查 使用委托异步调用 sync和await 总结 概述 最近在qq群里有一朋友,问起在winform中怎么通过开启线程的方式去处理耗时的操作,比如,查看某个目录下所有的文件,或 ...

  3. Thread类的常用方法_获取线程名称的方法和Thread类的常用方法_设置线程名称的方法

    构造方法: public Thread();分配一个新的线程对象 public Thread(String name);分配一个指定名字的新的线程对象 public Thread(Runnable t ...

  4. Linux 线程编程1.0

    在编译多线程程序的时候,需要连接libpthread文件: gcc pthread.c  -o  pthread  -lpthread: 所有线程一律平等,没有父子关系,线程属于进程. 创建线程用 p ...

  5. 在 POSIX 线程编程中避免内存泄漏

    检测和避免 POSIX 线程内存泄漏的技巧 POSIX 线程(pthread)编程定义了一套标准的 C 编程语言类型.函数和常量 — 且 pthreads 提供了一种强大的线程管理工具.要充分使用 p ...

  6. 线程池 | Java多线程,彻底搞懂线程池

    熟悉Java多线程编程的同学都知道,当我们线程创建过多时,容易引发内存溢出,因此我们就有必要使用线程池的技术了. 最近看了一些相关文章,并亲自研究了一下源码,发现有些文章还是有些问题的,所以我也总结了 ...

  7. python并发编程之多线程

    一  同步锁 注意: 1线程抢的是GIL锁,GIL锁就是执行权限,拿到权限后才能拿到互斥锁Lock,但是如果发现Lock没有被释放而阻塞,则立即交出拿到的执行权. 2join是等待所有,即整体串行,而 ...

  8. 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式

    1. 通过Executors创建线程池的弊端 在创建线程池的时候,大部分人还是会选择使用Executors去创建. 下面是创建定长线程池(FixedThreadPool)的一个例子,严格来说,当使用如 ...

  9. Executors创建的4种线程池的使用

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  10. wusir 线程间操作无效: 从不是创建控件“”的线程访问它 解决办法

    利用FileSystemWatcher设计一个文件监控系统时,如果一个文件被修改或者新建,则文件修改事件会被多次触发而产生多条信息.为了将一个文件被修改一次而产生的多条信息归结为一条,在设计中新开了一 ...

随机推荐

  1. 使用IndexedDB缓存给WebGL三维程序加速

    前言 使用webgl开发三维应用的时候,经常会发现三维场景加载比较慢,往往需要等待挺长时间,这样用户的体验就很不友好. 造成加载慢的原因,主要是三维应用涉及到的资源文件会特别多,这些资源文件主要是模型 ...

  2. Java程序设计(2021春)——第五章输入输出笔记与思考

    Java程序设计(2021春)--第五章输入输出笔记与思考 本章概览: 异常处理简介 程序运行时,环境.操作等可能出现各种错误.故障,我们希望程序具有容错能力,给出错误信息.面向对象的程序设计里有异常 ...

  3. keystore文件

    [-] keystore操作 运行时签名文件路径debug 生成签名文件打包时使用 获取MD5和SH1 修改keystore文件密码 修改keystore文件别名 修改keystore文件别名的密码 ...

  4. Linux下Mysql端口修改及防火墙开端口

    用户权限问题:https://blog.csdn.net/weixin_43670802/article/details/103019598 Linux下修改Mysql默认的3306端口 如下: 1. ...

  5. 抽象修饰符abstract

    描述一类事物的时候发现该类存在一种行为,但不知道行为具体怎么实现,我们将这种行为称之为抽象行为,这时候我们就需要抽象类 抽象类的好处:抽象类中的抽象方法一定要备子类重写 抽象类注意点: 1.在类中,一 ...

  6. iOS中JavaScript和OC交互 --by 胡 xu

    在iOS开发中很多时候我们会和UIWebView打交道,目前国内的很多应用都采用了UIWebView的混合编程技术,最常见的是微信公众号的内容页面.前段时间在做微信公众平台相关的开发,发现很多应用场景 ...

  7. 分配IP地址的好东西 DHCP以及NAT简单介绍

    主机配置协议DHCP 1.DHCP应用场景 2.DHCP基础原理 3.NAT简单介绍 4.配置命令 1.手工配置IP地址,工作量比较大而且不好管理,如果用户自己修改参数,可能会导致ip地址冲突,这个时 ...

  8. rust 实战 - 实现一个线程工作池 ThreadPool

    如何实现一个线程池 线程池:一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线 ...

  9. 微服务与SpiringBoot

    微服务: 微服务是一种架构风格,一般说到微服务都会说"微服务架构",即一个系统的各个功能(如结账,用户等)独立出来,以及各个服务独立出来,每个模块是可独立替换.可独立升级的软件单元 ...

  10. 生成一个node项目

    生成一个node项目1.创建文件夹2.文件夹中右键->在此处打开命令窗口->文件夹中打开dos3.执行:npm init //一路回车,最后y4.安装插件: C:\www\nodejs\h ...