【C++ 语言】线程 ( 线程创建方法 | 线程标识符 | 线程属性 | 线程属性初始化 | 线程属性销毁 | 分离线程 | 线程调度策略 | 线程优先级 | 线程等待 )(一)

简介: 【C++ 语言】线程 ( 线程创建方法 | 线程标识符 | 线程属性 | 线程属性初始化 | 线程属性销毁 | 分离线程 | 线程调度策略 | 线程优先级 | 线程等待 )(一)

I 线程创建方法


1. 线程创建方法函数原型 : int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void*), void *arg);


2. pthread_create 方法的 4 个参数 ;


参数 1 ( pthread_t *tidp ) : 线程标识符指针 , 该指针指向线程标识符 ;

参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ;

参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 , 其参数和返回值类型是 void* 类型 ;

参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ;

3. 返回值说明 :


线程创建成功 , 返回 0 ;

线程创建失败 , 返回 错误代码 ;

4. 关于函数指针参数的说明 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *)


函数的参数类型是 void* 指针 ;

函数的返回值类型 void* 指针 ;

5. 函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装 ;


6. 线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型 ;


7. 代码示例 :


/*
  线程创建方法函数原型 : 
  int pthread_create(
    pthread_t *tidp, 
    const pthread_attr_t *attr, 
    (void*)(*start_rtn)(void*), 
    void *arg);
  该方法需要提供四个参数 ;
    参数 1 ( pthread_t *tidp ) :线程标识符指针 , 该指针指向线程标识符 ;
    参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ;
    参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 , 
    其参数和返回值类型是 void* 类型
    参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ;
  返回值 :
    线程创建成功 , 返回 0 ;
    线程创建失败 , 返回 错误代码 ;
  关于函数指针参数 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *) ,
    函数的参数类型是 void* 指针
    函数的返回值类型 void* 指针
  函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装
  线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型
  */
  //函数指针 函数名 和 &函数名 都可以作为函数指针
  pthread_create(&pid , &attribute, pthread_function, hello);



II 线程执行函数


1. 线程执行函数的要求 : C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *) ;


2. 函数作用 : 将该函数的指针作为线程创建方法 pthread_create 的第三个参数 ;


3. 参数处理 : 在线程创建时 , 传入参数 , 将该参数转为 char* 字符串指针类型 , 将其打印出来 ;


4. 代码示例 :


/*
  定义线程中要执行的方法
  将该函数的指针作为线程创建方法 pthread_create 的第三个参数
  C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *)
*/
void* pthread_function(void* args) {
  //延迟 100 ms 执行
  //_sleep(100);
  //指针类型转换 : 将 void* 转为 char*
  //  使用 static_cast 类型转换标识符
  char* hello = static_cast<char*>(args);
  //打印参数
  cout << "pthread_function 线程方法 执行 参数 : " << hello << endl;
  return 0;
}




III 线程标识符


1. 线程标识符 : pthread_t 类型 , 用于声明线程的 ID ;


2. 类型本质 : 该类型是一个结构体 ;


typedef struct {
    void * p;                   /* Pointer to actual object */
    unsigned int x;             /* Extra information - reuse count etc */
} ptw32_handle_t;
typedef ptw32_handle_t pthread_t;


3. 代码示例 : 声明线程标识符 , 下面的代码是在栈内存中声明线程标识符 , pthread_create 方法中需要传入指针 , 这里使用取地址符获取其指针 ;


//线程标识符 , 这里需要传入指针 , 因此这里使用 & 取地址符获取其地址当做指针变量
  pthread_t pid;



IV 线程属性


1. 线程属性 : pthread_attr_t 表示线程属性类型 , 查看其类型声明 , 得到如下代码 , pthread_attr_t 类型是一个指针类型 ;


typedef struct pthread_attr_t_ * pthread_attr_t;


2. 线程属性声明 : 线程属性类型是一个指针 , 初始化时其值是随机值 , 是个野指针 , 这里将其设置为 0 ;


pthread_attr_t attribute = 0;


3. 线程属性的初始化和销毁 : 该线程属性需要先进行初始化和销毁;


① 线程属性初始化 : 函数原型 int pthread_attr_init(pthread_attr_t *attr); ; 初始化线程属性时 , 对属性进行了默认配置 ;

pthread_attr_init(&attribute);


② 线程属性销毁 : 函数原型 int pthread_attr_destroy(pthread_attr_t *attr); ;

//销毁线程属性
  pthread_attr_destroy(&attribute);


4. 二维指针参数 :


① 参数说明 : 线程初始化和销毁方法传入 pthread_attr_t * 类型的参数 , pthread_attr_t 类型是指针 , pthread_attr_t * 是 二维指针 ; 初始化时 , 肯定要创建一个有实际意义的线程属性结构体 , 将 attribute 二维指针指向线程属性结构体指针 ;

② 指向指针的指针意义 : 在传递时可以 在函数内部 修改指针指向的地址 ;

5. 代码示例 :

/*
  线程属性结构体变量
    该线程属性需要先进行初始化和销毁;
    线程属性初始化方法 : int pthread_attr_init(pthread_attr_t *attr);
    线程属性销毁方法 : int pthread_attr_destroy(pthread_attr_t *attr);
  线程属性类型定义 : typedef struct pthread_attr_t_ * pthread_attr_t;
    pthread_attr_t 其本质是一个指针 ; 
    pthread_attr_t attribute 声明后 , 该指针是野指针 , 需要将其设置为 0 ;
  */
  pthread_attr_t attribute = 0;
  //初始化线程属性, 此处的参数是指针的指针 , 该指针指向 0 地址 ; 
  //  初始化时 , 肯定要创建一个有实际意义的线程属性结构体 , 将 attribute 二维指针 指向结构体指针
  //  指向指针的指针意义 : 在传递时可以在函数内部修改指针指向的地址 ; 
  //初始化线程属性时 , 对属性进行了默认配置 ;
  pthread_attr_init(&attribute);




V 线程属性 1 ( 分离线程 | 非分离线程 )


1. 线程的默认属性 : 线程创建后 , 默认是非分离线程 ;


2. 非分离线程 :


① 特点 : 非分离线程允许在其它线程中 , 来等待另外线程执行完毕 ;

② 表现 : 创建线程后 , 线程执行 , 如果调用 pthread_join 函数 , 其作用是等待 pthread_function 线程函数执行完毕 ;

3. 分离线程 : 不能被其它线程操作 , 如调用 pthread_join 函数 , 无法等待该分离线程执行完毕 ;


4. 非分离线程 与 分离线程 比较 :


① 设置非分离线程属性 : 先执行完线程内容 , 等待线程执行完毕后 , 才执行 pthread_join 后的代码 ;

② 设置分离线程属性 : pthread_join 等待线程执行完毕是无效的 , 主线程会继续向后执行 , 不会等待线程执行完毕

5. 分离线程不经常使用 : 一般情况下是不经常将线程设置为分离线程 , 如果设置了 , 那么该线程就无法进行控制 ;


6. 设置线程为分离线程代码示例 :


pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_DETACHED);



目录
相关文章
|
9天前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
9天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
2月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
2月前
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
96 2
|
3月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
41 3
|
3月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
28 2
|
3月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
26 1
|
3月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
51 1
|
3月前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
37 1
|
3月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
57 1