1.线程的基本概念
线程是进程内的一个执行单元,是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享进程的资源,如内存空间、文件描述符等。例如,一个文本编辑器进程可能有一个线程用于接收用户输入,另一个线程用于在后台保存文件,它们都在同一个进程的资源环境下工作。
2.线程与进程的区别
资源分配:
进程是资源分配的基本单位,每个进程都有自己独立的地址空间、内存、文件描述符等资源。当一个进程启动时,操作系统会为它分配一系列的资源。而线程共享所属进程的资源,例如,多个线程在同一个进程中可以访问相同的全局变量和堆内存区域。
调度开销:
进程间的切换开销较大,因为需要切换内存空间、刷新缓存等操作。当操作系统从一个进程切换到另一个进程时,需要保存当前进程的状态(如程序计数器、寄存器等),然后加载新进程的状态。
而线程间的切换开销相对较小,因为它们共享进程的大部分资源,主要是切换线程的执行上下文(如栈指针、程序计数器等)。
3.线程编程API说明
1.线程创建函数:pthread_create,用于创建一个新的线程。
pthread_create函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
参数说明:
thread:是一个指向pthread_t类型的指针,用于存储新创建线程的标识符。pthread_t类型在不同的系统上可能有不同的定义,但通常是一个整数类型或者结构体类型,用于唯一标识一个线程。
attr:是一个指向pthread_attr_t类型的指针,用于设置线程的属性。如果传入NULL,则表示使用默认属性创建线程。线程属性可以包括线程的栈大小、调度策略等内容。
start_routine:是一个函数指针,指向新线程要执行的函数。这个函数的返回值是void*类型,参数也是void*类型。这意味着可以将各种类型的数据通过arg参数传递给线程函数,并且线程函数可以返回一个指针类型的数据。
arg:是传递给start_routine函数的参数。
2.线程等待函数:pthread_join,主线程调用pthread_join函数来等待指定线程结束。
pthread_join函数原型:
int pthread_join(pthread_t thread, void **retval)
参数说明:
thread:是要等待的线程的标识符,即pthread_create函数返回的pthread_t类型的值。
retval:是一个指向`void*`类型的指针的指针,用于接收被等待线程的返回值。如果不需要接收返回值,可以传入NULL。
3.线程退出函数:pthread_exit,在线程函数内部调用pthread_exit函数可以使线程正常退出。
pthread_exit函数原型:
void pthread_exit(void *retval)
参数说明:
retval:是一个void*类型的指针,用于返回线程的退出状态。这个值可以被其他线程通过pthread_join函数接收。
4.创建单个线程示例代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg) {
// 线程函数体
int *num = (int *)arg;
printf("Thread received number: %d\n", *num);
// 实际应用中通常在这里使用while(1){}来循环执行线程内部代码。
pthread_exit(NULL);
}
int main() {
pthread_t thread_id;
int num = 10;
int ret = pthread_create(&thread_id, NULL, thread_function, &num);
if (ret!= 0) {
perror("pthread_create");
return 1;
}
// 实际编程中通常在这里使用while(1){}来循环执行主线程代码。
// 等待线程结束
pthread_join(thread_id, NULL);
return 0;
}
5.创建多个线程示例代码,同时使用互斥量来保护共享资源
互斥量Mutex::互斥量是一种用于保护共享资源的同步原语。它的作用是确保在同一时刻只有一个线程能够访问被保护的共享资源。当一个线程想要访问共享资源时,它必须先获取互斥量的锁,如果互斥量已经被其他线程锁住,那么这个线程就会被阻塞,直到互斥量被解锁。
互斥量初始化函数: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
参数说明:mutex:是指向pthread_mutex_t类型的指针,attr:是指向互斥量属性的指针,如果传入NULL,则使用默认属性初始化。
加锁函数:int pthread_mutex_lock(pthread_mutex_t *mutex),用于获取互斥量的锁,如果互斥量已经被其他线程锁住,调用线程会被阻塞。
解锁函数:int pthread_mutex_unlock(pthread_mutex_t *mutex),用于释放互斥量的锁,使得其他等待该互斥量的线程可以获取锁。
销毁函数: int pthread_mutex_destroy(pthread_mutex_t *mutex),用于销毁一个已经初始化的互斥量。在销毁互斥量之前,需要确保没有线程正在使用这个互斥量。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;
int shared_variable = 0;
void *thread_function(void *arg) {
pthread_mutex_lock(&mutex);
// 访问共享变量
shared_variable++;
printf("Thread incremented shared variable to: %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main() {
pthread_t thread_id1, thread_id2;
int ret;
// 初始化互斥量
ret = pthread_mutex_init(&mutex, NULL);
if (ret!= 0) {
perror("pthread_mutex_init");
return 1;
}
ret = pthread_create(&thread_id1, NULL, thread_function, NULL);
if (ret!= 0) {
perror("pthread_create");
return 1;
}
ret = pthread_create(&thread_id2, NULL, thread_function, NULL);
if (ret!= 0) {
perror("pthread_create");
return 1;
}
pthread_join(thread_id1, NULL);
pthread_join(thread_id2, NULL);
// 销毁互斥量
pthread_mutex_destroy(&mutex);
return 0;
}