线程的使用学习pthread_create函数详解(向线程函数传递参数)以及linux中pthread_join()与pthread_detach()详解和#define和#ifdef的使用#if 1

一 、# 线程的使用学习pthread_create函数详解 #原文出处

一、pthread_create函数:

1、简介:pthread_create是UNIX环境创建线程的函数

2、头文件:#include <pthread.h>

3、函数声明:

int pthread_create(pthread_t* restrict tidp,const pthread_attr_t* restrict_attr,void* (*start_rtn)(void*),void *restrict arg);

4、输入参数:(以下做简介,具体参见实例一目了然)

(1)tidp:事先创建好的pthread_t类型的参数。成功时tidp指向的内存单元被设置为新创建线程的线程ID。

(2)attr:用于定制各种不同的线程属性。APUE的12.3节讨论了线程属性。通常直接设为NULL。

(3)start_rtn:新创建线程从此函数开始运行。无参数是arg设为NULL即可。

(4)arg:start_rtn函数的参数。无参数时设为NULL即可。有参数时输入参数的地址。当多于一个参数时应当使用结构体传入。(以下举例)

5、返回值:成功返回0,否则返回错误码。

6、说明。

传递参数的时候传地址: pthread_create(&ntid, NULL, thr_fn, &param1);

线程函数的第一句通常是获取传入参数:Param tmp = *(Param *)arg;

举例如下:

二、不向线程函数传递参数:

#include "apue.h"
#include <pthread.h>
#include "apueerror.h"
#include <iostream>
#include <string>
 
using namespace std;
 
pthread_t ntid;
 
void printids(const char *s){
	pid_t		pid;
	pthread_t	tid;
 
	pid = getpid();
	tid = pthread_self();
	printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,
	  (unsigned long)tid, (unsigned long)tid);
}
 
 
void *thr_fn(void *arg){
    cout << "----enter sub thread--------" << endl;
	printids("new thread: ");
	cout << "Change to C++ code!!" << endl;
    cout << "----exit from sub thread----" << endl;
	return((void *)0);
}
 
int main(void){
	int		err;
    //第四个参数为NULL,说明没有向线程函数传参数。
	err = pthread_create(&ntid, NULL, thr_fn, NULL);
	if (err != 0)
		err_exit(err, "can't create thread");
	printids("main thread:");
	sleep(1);
	exit(0);
}

三、向线程函数传递一个参数:

#include "apue.h"
#include <pthread.h>
#include "apueerror.h"
#include <iostream>
#include <string>
using namespace std;
pthread_t ntid;
void printids(const char *s){
	pid_t		pid;
	pthread_t	tid;
 
	pid = getpid();
	tid = pthread_self();
	printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,
	  (unsigned long)tid, (unsigned long)tid);
}
 
struct Param {
	int a;
	int b;
	int c;
};
 
 
void *thr_fn( void *arg ) {
    cout << "----enter sub thread--------" << endl;
	int tmp = *(int *)arg;
	cout << "tmp=" << tmp << endl;
	printids("new thread: ");
	cout << "Change to C++ code!!" << endl;
    cout << "----exit from sub thread----" << endl;
	return((void *)0);
}
 
 
 
int main(void){
	int		err;
	int num = 123;
    //向线程函数传入一个参数。
	err = pthread_create(&ntid, NULL, thr_fn, &num);
	if (err != 0)
		err_exit(err, "can't create thread");
	printids("main thread:");
	sleep(1);
	exit(0);
}

 四、向线程函数传递两个或以上的参数

#include "apue.h"
#include <pthread.h>
#include "apueerror.h"
#include <iostream>
#include <string>
using namespace std;
pthread_t ntid;
 
void printids(const char *s){
	pid_t		pid;
	pthread_t	tid;
 
	pid = getpid();
	tid = pthread_self();
	printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,
	  (unsigned long)tid, (unsigned long)tid);
}
 
struct Param {
	int a;
	int b;
	int c;
};
 
 
void *thr_fn(void *arg) {
    cout << "----enter sub thread--------" << endl;
	Param tmp = *(Param *)arg;
	cout << "tmp.a=" << tmp.a << endl;
	cout << "tmp.b=" << tmp.b << endl;
	cout << "tmp.c=" << tmp.c << endl;
 
	printids("new thread: ");
	cout << "Change to C++ code!!" << endl;
    cout << "----exit from sub thread----" << endl;
	return((void *)0);
}
 
int main(void){
	int		err;
	int num = 123;
	Param param1;
	param1.a = 11;
	param1.b = 22;
	param1.c = 33;
    //通过结构体向线程函数传入多个参数
	err = pthread_create(&ntid, NULL, thr_fn, &param1);
 
	if (err != 0)
		err_exit(err, "can't create thread");
	printids("main thread:");
	sleep(1);
	exit(0);
}

二、 #pthread_join()与pthread_detach()详解#

前言:
1.linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。
2.unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。或者将线程置为 joinable,然后适时调用pthread_join.
3.其实简单的说就是在线程函数头加上 pthread_detach(pthread_self())的话,线程状态改变,在函数尾部直接 pthread_exit线程就会自动退出。省去了给线程擦屁股的麻烦。

eg:

 pthread_t tid;
 int status = pthread_create(&tid, NULL, ThreadFunc, NULL);
 if(status != 0)
 {
  perror("pthread_create error");
 }
 pthread_detach(tid);

一:pthread_join()
(1)pthread_join()即是子线程合入主线程,主线程阻塞等待子线程结束,然后回收子线程资源。

(2)函数说明

1)头文件 : #include <pthread.h>

2)函数定义: int pthread_join(pthread_t thread, void **retval);

3)描述 :pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。

4)参数 :thread: 线程标识符,即线程ID,标识唯一线程。retval: 用户定义的指针,用来存储被等待线程的返回值。

5)返回值 : 0代表成功。 失败,返回的则是错误号。

(3)实例

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
 
void *thread_function(void *arg)
{
  int i;
  for ( i=0; i<8; i++)
 {
    printf("Thread working...! %d \n",i);
    sleep(1);
  }
  return NULL;
}
 
int main(void)
{
  pthread_t mythread;
 
  if ( pthread_create( &mythread, NULL, thread_function, NULL) )
 {
    printf("error creating thread.");
    abort();
  }
  if ( pthread_join ( mythread, NULL ) )
 {
    printf("error join thread.");
    abort();
  }
 
  printf("thread done! \n");
  exit(0);
}

三、##define和#ifdef的使用#

之前没有写过什么大工程,所以没有怎么关注过条件编译。今天在看代码的时候发现里面用到了#define和#ifdef来调试代码。于是就看了一下。顺便再做个笔记。

先介绍一下条件编译:

       条件编译是根据实际定义的宏(可以认为是某一类条件)进行代码静态编译的手段。可以根据表达式的值或者某个特定宏是否被定义来确定编译条件。

在看几个预编译指令(预编译指令很多,这次只介绍用到的三个):

#define             定义一个预处理宏                                                                                                                                                         

#undef              取消宏的定义

#ifdef                 判断某个宏是否被定义,若已定义,执行随后的语句

#else                 与#if、#ifdef、#ifndef对应,若这些条件不满足,则执行#else之后的语句,相当于C中的else

#endif                是#if、#ifdef、#ifndef这些条件命令结束的标志

下面看一个很简单的条件编译例子:

#include<stdio.h>
 
#define CONDITION_1
 
int main(int argc, char **argv)
{
#ifdef CONDITION_1
    printf("CONDITION_1!\n");
#else
    printf("no CONDITION_1!\n");
#endif
    return 0;
}

##if 0 或 #if 1(C语言注释)#

C语言注释有三种方法
常见的方法有:1)单行注释: //
                          2)多行注释: /* */
今天我想和初学者来聊聊一种相对不那么熟悉的C语言注释方法:利用条件编译注释代码。

3)#if 0  或  #if 1注释:
当屏蔽掉大块代码时,使用"#if 0"比使用"/**/"要好。(因为用"/**/"做大段的注释时,需要防止被注释掉的代码段中有嵌套的"/**/",一旦出现"/**/"嵌套"/**/"的情况,会导致你注释掉的代码区域并不是你想要的区域范围) 

情况一:常见的一中,如有一段不想要的代码,可以直接用"#if 0 ... #endif"形式来注释,效果等同于"/**/"

#if 0
    ...程序段...
#endif
情况二:选择结构的条件编译。(如果常量为真【非0,随便什么数字,只要不是0】,就执行程序段1,否则执行程序段2。)

#if 常量
    ...程序段1...
#else
    ...程序段2...
#endif
情况三:嵌套情况。(如果常量a为真【非0,随便什么数字,只要不是0】,就执行程序段1。当常量a为0且常量b为真时,执行程序段2;当常量a为0且常量b为0时,执行程序段3)

#if 常量a
    ...程序段1...
#else
        #if 常量b
          ...程序段2...
        #else
          ...程序段3...
      #endif
#endif
 

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
pthread_detach函数的原型为: ```c #include <pthread.h> int pthread_detach(pthread_t thread); ``` 该函数的作用是将指定的线程标记为“可分离的”,也就是在该线程结束时,该线程的资源(如栈空间等)可以被自动回收,而不需要其他线程调用pthread_join函数来等待线程退出并回收资源。 需要注意的是,一旦调用pthread_detach函数线程标记为“可分离的”,就不能再调用pthread_join函数来等待该线程结束了。否则会返回错误码EINVAL(无效参数)。 另外,线程默认是“可连接的”,也就是需要其他线程调用pthread_join函数来回收资源。如果不需要回收线程资源,可以调用pthread_detach函数线程标记为“可分离的”,以避免资源泄漏和死锁等问题。 但是需要注意的是,调用pthread_detach函数的前提是线程已经退出。如果线程还没有退出,调用pthread_detach函数可能会导致未定义的行为。因此,一般情况下,需要在创建线程时指定线程属性为“可分离的”,以确保线程退出时可以自动回收资源。例如: ```c pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置线程属性为“可分离的” pthread_create(&tid, &attr, thread_func, arg); pthread_attr_destroy(&attr); ``` 这里调用了pthread_attr_setdetachstate函数线程属性设置为“可分离的”,以确保线程退出时可以自动回收资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无证驾驶梁嗖嗖

让我们解决Jetson使用问题

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值