pthread 基础编程

简介:
所谓最简单的多线程编程,就是通过pthread_create,pthread_join,pthread_exit 3个api实现线程的创建与终止,而创建的线程只做些简单的工作,如printf一些文字信息。
        使用pthread_create,pthread_join,pthread_exit 进行多线程编程的模型如下图所示:


1 最简单的pthread多线程hello world示例

  1. 使用pthread多线程库,通过main 主线程创建 5个子线程
  2. 每个子线程的工作相同,就是打印出“pthread's Hello World!
  3. main主线程等待5个子线程全部退出后,main主线程退出(整个程序退出)。

2 关键代码

void *hello_world_thread(void *arg)
{
   printf("pthread's Hello World!\n");

   pthread_exit(NULL);

   return NULL;
}

pthread_create(&threads[i], NULL,hello_world_thread, NULL);

pthread_join(threads[i], NULL);


3 运行结果


通过程序的运行结果,可以确认

  1. 确实创建了5个子线程,分别打印了pthread's Hello World!
  2. 主线程等待了5个子线程退出之后才退出

但是我不能确认5个子线程的执行顺序,即“pthread's Hello World!”分别是由哪个子线程打印的,从运行结果上是无法确认的。


/******************************************************************************
* 文件名称: hello.c
* 文件描述: 一个类似“hello wrold”的pthread入门程序,用于说明线程(thread)的
*     创建和终止
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define HELLO_WORLD_THREAD_NUM  5

void *hello_world_thread(void *arg)
{
   printf("pthread's Hello World!\n");
	/**  
	* @function void pthread_exit(void *status)
	*     终止调用者线程,
	* @param status:
	*     通过status设置退出状态,与pthread_join配对使用
	* @return :
	*     无返回值,也不返回到其调用方。
	* @note 
	*     如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
	*     否则,将忽略status。线程ID 可以立即回收。
	*/
   pthread_exit(NULL);

   return NULL;
}

int main(int argc, char *argv[])
{
	pthread_t threads[HELLO_WORLD_THREAD_NUM];
	int rc;
	int i;
	for(i=0;i<HELLO_WORLD_THREAD_NUM;i++)
	{
		/**  
		* @function int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg)
		*     按照给定的线程属性attr,在一个进程(process)里创建一个新的线程(thread)
		* @param attr:
		*     如果attr为NULL,则内部使用默认的属性创建线程。如果在创建线程之后修改attr,则不会对已经创建的线程产生作用。
		* @param thread:
		*     创建线程成功后,将thread id存储在thread里,返回给调用者。否则thrad的值是未定义的。
		* @param start_routine:
		*     线程创建成功后,开始执行线程的入口函数start_routine。
		* @param arg:
		*     调用者通过arg指定线程入口函数start_routine专用的参数指针。
		* @return :
		*     0 创建成功返回0
		*     EAGAIN 超出了系统限制,如创建的线程太多,一个进程最多创建线程个数PTHREAD_THREADS_MAX。
		*     EINVAL attr 的值无效
		* @note pthread_create创建线程后,线程入口函数即开始执行,不需要显示控制start_routine开始执行。
		*     如果确实需要将此过程分为create和start2步来控制start_routine稍后执行,
		*     start_routine可以通过等待一个条件变量(condition variable)进行同步的方式实现。
		*/
		rc = pthread_create(&threads[i], NULL, hello_world_thread, NULL);
		if (rc)
		{
			printf("ERROR: pthread_create failed with %d\n", rc);
			return -1;
		}
	}

	for(i=0;i<HELLO_WORLD_THREAD_NUM;i++)
	{
		/**  
		* @function int pthread_join(pthread_t thread, void **status);
		*     等待thread线程终止
		*     如果thread指代的线程还没有终止,将导致调用线程挂起,直到thread指代的线程终止为止。
		* @param thread:
		*     所等待的的终止线程
		* @param status:
		*     如果status的值不等于NULL,那么它的值是通过pthread_exit传递过来的。
		* @return :
		*     0 线程已经终止
		*     ESRCH 多个线程不能等待同一个线程完成,否则仅有一个线程会成功完成。其他线程将终止,并返回ESRCH 错误。
		*     EINVAL 一般表示thread是无效的参数
		*     EDEADLK 检查到死锁状态
		* @note 
		*     如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
		*     否则,将忽略status。线程ID 可以立即回收。
		*/
		pthread_join(threads[i], NULL);
	}
	
	printf("INFO: All threads have been exit!!!\n");

	return 0;
}


相关文章
|
19天前
|
安全 程序员 API
|
3月前
|
存储 安全 Unix
并发编程基础:使用POSIX线程(pthread)进行多线程编程。
并发编程基础:使用POSIX线程(pthread)进行多线程编程。
88 0
|
3月前
|
测试技术 Go
|
安全 Go 数据安全/隐私保护
Golang 语言中基础同步原语 Mutex 和 RWMutex 的区别
Golang 语言中基础同步原语 Mutex 和 RWMutex 的区别
93 0
|
6月前
|
设计模式 缓存 安全
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
107 0
|
6月前
|
算法 调度
FreeRTOS入门教程(互斥锁的概念和函数使用)
FreeRTOS入门教程(互斥锁的概念和函数使用)
350 0
|
6月前
|
存储 API 数据安全/隐私保护
FreeRTOS入门教程(信号量的概念及API函数使用)
FreeRTOS入门教程(信号量的概念及API函数使用)
365 0
|
Go 调度
Go语言,Mutex 实现原理
Mutex 使用非常方便,但它的内部实现却复杂的很,今天我们来介绍下它的内部实现原理。
150 0
Go语言,Mutex 实现原理
|
安全 C语言 Python
Python核心基础必备(多线程、多进程编程)(Queue,Lock/Rlock,Condition,Semaphore)
前言 一个人活在这个世界上为了什么呢?我觉得是去经历和享受。对于没做过的事情要做一做。 每个人在年轻的时候,所做出的的选择是没有对错之分的,所有的选择都是对的,只能说对于所做选择的结果,只是好与更好的差别。每个人都有自己衡量事物的价值观,我们有什么样的认知就会投影出什么样的图像,所以一定要不断超越有限的认知,不断地提升内外的自由度,不要尝试让自己假装看起来很努力,因为结果不会陪你演戏! 学习如逆水行舟 不进则退
Python核心基础必备(多线程、多进程编程)(Queue,Lock/Rlock,Condition,Semaphore)
|
安全 Go Android开发
Go语言核心手册-8.sync.WaitGroup
WaitGroup是开箱即用和并发安全的,可以通过它很方便地实现一对多goroutine协作流程,即:一个分发子任务的goroutine,和多个执行子任务的goroutine,共同来完成一个较大的任务。在使用WaitGroup值的时候,我们一定要注意,千万不要让其中的计数器的值小于0,否则就会引发 panic。另外,我们最好用“先统一Add,再并发Done,最后Wait”这种标准方式,来使用WaitGroup值, 尤其不要在调用Wait方法的同时,并发地通过调用Add方法去增加其计数器的值,因为这也有可能引发 panic。
149 0
Go语言核心手册-8.sync.WaitGroup