并发编程基础:使用POSIX线程(pthread)进行多线程编程。

简介: 并发编程基础:使用POSIX线程(pthread)进行多线程编程。

并发编程基础:使用POSIX线程(pthread)进行多线程编程。

 

并发编程是现代软件开发中不可或缺的一部分,它允许程序同时执行多个任务,从而提高程序的效率和响应性。POSIX 线程(pthread)是 UNIX 和类 UNIX 系统(如 Linux)上实现多线程的一种标准方式。下面将介绍使用 pthread 进行多线程编程的基础。

1. 包含头文件

要使用 pthread,首先需要包含 pthread 库的头文件:

c复制代码

#include <pthread.h>

2. 创建线程

在 pthread 中,线程是通过 pthread_create 函数创建的。这个函数需要四个参数:一个指向 pthread_t 类型的指针(用于存储新线程的标识符),一个指向线程属性对象的指针(通常传递 NULL 以使用默认属性),一个指向线程将要执行的函数的指针,以及传递给该函数的参数(通过 void* 传递)。

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

 

void* thread_function(void* arg) {

// 线程执行的代码

printf("Hello from thread\n");

return NULL;

}

 

int main() {

pthread_t thread_id;

int result = pthread_create(&thread_id, NULL, thread_function, NULL);

if (result != 0) {

perror("Failed to create thread");

exit(EXIT_FAILURE);

}

 

// 等待线程结束

pthread_join(thread_id, NULL);

 

return 0;

}

3. 线程同步

多个线程可能会同时访问共享资源,这可能导致数据竞争和不一致。为了解决这个问题,pthread 提供了多种同步机制,如互斥锁(mutexes)、条件变量(condition variables)和信号量(semaphores)。

互斥锁(Mutexes)

互斥锁用于保护共享数据,确保同一时间只有一个线程可以访问该数据。

#include <pthread.h>

 

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

 

void* thread_function(void* arg) {

pthread_mutex_lock(&lock);

// 访问共享资源

pthread_mutex_unlock(&lock);

return NULL;

}

4. 线程终止

线程可以通过返回其函数来正常终止,或者可以通过 pthread_exit 函数提前终止。主线程可以使用 pthread_join 等待其他线程完成。

5. 编译和链接

编译使用 pthread 的程序时,需要链接 pthread 库。在 GCC 中,这通常通过添加 -lpthread 选项来完成。

gcc -o my_program my_program.c -lpthread

6. 注意事项

确保所有线程都正确同步,以避免数据竞争和死锁。

在多线程程序中,对全局变量和静态变量的访问应该特别小心。

线程安全函数:确保你使用的库函数是线程安全的,或者你的使用方式是线程安全的。

调试多线程程序可能比调试单线程程序更复杂,因为存在非确定性行为。

通过使用 pthread,你可以有效地利用现代多核处理器的并行处理能力,编写出高效、响应快的并发程序。

 

 

并发编程基础:使用POSIX线程(pthread)进行多线程编程。(扩展)

并发编程与 POSIX 线程(pthread)深入解析

在现代软件开发中,并发编程已成为提升程序性能和响应能力的关键技术之一。POSIX 线程(pthread)作为 UNIX 和类 UNIX 系统(如 Linux)上实现多线程的标准方式,提供了丰富的API以支持复杂的多线程应用程序开发。本文将详细探讨使用 pthread 进行多线程编程的基础、线程同步机制、线程终止与资源清理,以及编译和链接的注意事项。

一、包含头文件与基础设置

在使用 pthread 之前,首先需要包含 pthread 库的头文件。这是任何使用 pthread 功能的程序所必需的。

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

二、创建线程

在 pthread 中,线程通过 pthread_create 函数创建。这个函数需要四个参数:线程标识符的指针、线程属性对象指针(通常传递 NULL 以使用默认属性)、线程执行函数的指针以及传递给该函数的参数(通过 void* 传递)。

void* thread_function(void* arg) {

printf("Hello from thread\n");

return NULL;

}

 

int main() {

pthread_t thread_id;

int result = pthread_create(&thread_id, NULL, thread_function, NULL);

if (result != 0) {

perror("Failed to create thread");

exit(EXIT_FAILURE);

}

 

// 等待线程结束

pthread_join(thread_id, NULL);

return 0;

}

在上面的例子中,thread_function 是线程将要执行的函数,而 pthread_create 被用来创建新线程。主线程通过调用 pthread_join 等待新线程结束,以确保程序在所有线程完成前不会退出。

三、线程同步

当多个线程需要访问共享资源时,必须采取适当的同步措施来避免数据竞争和不一致。pthread 提供了多种同步机制,包括互斥锁(mutexes)、条件变量(condition variables)和信号量(semaphores)。

3.1 互斥锁(Mutexes)

互斥锁用于保护共享数据,确保同一时间只有一个线程可以访问该数据。

#include <pthread.h>

 

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

 

void* thread_function(void* arg) {

pthread_mutex_lock(&lock);

// 访问共享资源

printf("Accessing shared resource\n");

pthread_mutex_unlock(&lock);

return NULL;

}

 

int main() {

// 线程创建和等待代码...

}

在 thread_function 中,使用 pthread_mutex_lock 和 pthread_mutex_unlock 分别对互斥锁进行加锁和解锁操作,以保护共享资源的访问。

3.2 条件变量

条件变量与互斥锁配合使用,允许线程等待某个条件成立。

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

 

void* thread_function(void* arg) {

pthread_mutex_lock(&lock);

// 等待条件满足

pthread_cond_wait(&cond, &lock);

// 条件满足,处理数据

printf("Condition met, processing data\n");

pthread_mutex_unlock(&lock);

return NULL;

}

 

// 在另一个线程或函数中设置条件并通知等待的线程

pthread_mutex_lock(&lock);

// 修改条件...

pthread_cond_signal(&cond); // 或 pthread_cond_broadcast(&cond)

pthread_mutex_unlock(&lock);

四、线程终止与资源清理

线程可以通过两种方式终止:正常返回其函数值或调用 pthread_exit 函数提前终止。主线程或其他线程可以使用 pthread_join 等待特定线程结束,并可选地获取该线程的退出状态。

void* thread_function(void* arg) {

// 线程执行代码

// ...

return (void*)0; // 正常退出

// 或 pthread_exit((void*)EXIT_SUCCESS); // 提前退出

}

 

int main() {

// 线程创建和等待代码...

void* status;

pthread_join(thread_id, &status);

if (status == (void*)0) {

printf("Thread exited normally\n");

}

// ...

}

 

相关文章
|
2月前
|
人工智能 安全 调度
Python并发编程之线程同步详解
并发编程在Python中至关重要,线程同步确保多线程程序正确运行。本文详解线程同步机制,包括互斥锁、信号量、事件、条件变量和队列,探讨全局解释器锁(GIL)的影响及解决线程同步问题的最佳实践,如避免全局变量、使用线程安全数据结构、精细化锁的使用等。通过示例代码帮助开发者理解并提升多线程程序的性能与可靠性。
113 0
|
2月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
138 0
|
4月前
|
Java 开发者 Kotlin
华为仓颉语言初识:并发编程之线程的基本使用
本文详细介绍了仓颉语言中线程的基本使用,包括线程创建(通过`spawn`关键字)、线程名称设置、线程执行控制(使用`get`方法阻塞主线程以获取子线程结果)以及线程取消(通过`cancel()`方法)。文章还指出仓颉线程与Java等语言的差异,例如默认不提供线程名称。掌握这些内容有助于开发者高效处理并发任务,提升程序性能。
170 2
|
4月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
188 0
|
2月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
3月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
234 5
|
4月前
|
Linux 程序员 API
CentOS如何使用Pthread线程库
这就是在CentOS下使用Pthread线程库的全过程。可见,即使是复杂的并发编程,只要掌握了基本的知识与工具,就能够游刃有余。让我们积极拥抱并发编程的魅力,编写出高效且健壮的代码吧!
101 11
|
7月前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
241 20
|
7月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
131 26
|
7月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
135 17