上海哪学网站建设优化,删格化网站设计,常用的关键词挖掘工具有哪些,网站开发与规划目录 一、线程概述
二、线程创建
三、线程终止
四、线程回收
五、线程取消
六、线程分离
七、线程安全 一、线程概述
线程是进程内的一个执行单元#xff0c;是进程内可调度的实体。一个进程可以包含多个线程#xff0c;这些线程共享进程的资源#xff0c;如内存空…
目录 一、线程概述
二、线程创建
三、线程终止
四、线程回收
五、线程取消
六、线程分离
七、线程安全 一、线程概述
线程是进程内的一个执行单元是进程内可调度的实体。一个进程可以包含多个线程这些线程共享进程的资源如内存空间、文件描述符等但拥有各自独立的程序计数器、栈和寄存器等执行上下文。线程相较于进程创建和切换开销更小能更有效地利用多核处理器资源提高程序的并发性能。 二、线程创建
在 Linux 中使用 pthread_create 函数来创建线程其函数原型如下
#include pthread.h
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);
thread指向 pthread_t 类型的指针用于存储新创建线程的标识符。attr指向 pthread_attr_t 类型的指针用于设置线程的属性若为 NULL则使用默认属性。start_routine是一个函数指针指向线程开始执行的函数该函数返回值为 void* 类型参数也为 void* 类型。arg传递给 start_routine 函数的参数。
示例代码
#include stdio.h
#include pthread.h
#include stdlib.h
#include unistd.hvoid *thread_function(void *arg) {// 线程函数这里简单打印线程 ID 和传入的参数int num *(int *)arg;printf(线程 ID%lu参数%d\n, pthread_self(), num);pthread_exit(NULL);
}int main() {pthread_t thread_id;int num 10;// 创建线程if (pthread_create(thread_id, NULL, thread_function, (void *)num)! 0) {perror(线程创建失败);exit(EXIT_FAILURE);}// 主线程继续执行其他任务这里简单睡眠一段时间sleep(2);// 等待线程结束可选这里只是为了确保线程在主线程退出前完成pthread_join(thread_id, NULL);printf(主线程结束\n);return 0;
}
在上述代码中首先定义了一个线程函数 thread_function它接受一个 void* 类型的参数并在线程中打印线程 ID 和传入的参数值。在 main 函数中创建了一个线程将 num 的地址作为参数传递给线程函数。主线程睡眠一段时间后可以选择调用 pthread_join 等待子线程结束确保子线程资源被正确回收后主线程再退出。 三、线程终止
线程可以通过以下几种方式终止
1.线程函数自然返回线程函数执行完所有指令后返回线程自动终止。
2.调用 pthread_exit 函数线程可以在任何位置调用 pthread_exit 函数来显式终止自身并可以返回一个指向线程退出状态的指针。
函数原型void pthread_exit(void *retval);
示例代码
#include stdio.h
#include pthread.h
#include stdlib.hvoid *thread_function(void *arg) {// 线程执行一些任务后主动终止printf(线程即将终止\n);pthread_exit(NULL);
}int main() {pthread_t thread_id;// 创建线程if (pthread_create(thread_id, NULL, thread_function, NULL)! 0) {perror(线程创建失败);exit(EXIT_FAILURE);}// 等待线程结束这里只是为了演示主线程的行为实际上对于主动退出的线程等待并非必需pthread_join(thread_id, NULL);printf(主线程继续执行\n);return 0;
}
在上述代码中线程函数 thread_function 执行到 pthread_exit(NULL) 时线程终止主线程可以通过 pthread_join 来等待该线程结束以确保线程资源被正确回收。 四、线程回收
pthread_join 函数用于回收已经终止的线程资源并获取线程的退出状态如果线程通过 pthread_exit 传递了退出状态。
函数原型int pthread_join(pthread_t thread, void **retval);
thread要等待回收的线程 ID。
retval用于存储线程的退出状态指针如果不关心线程的退出状态可以传入 NULL。
示例代码
#include stdio.h
#include pthread.h
#include stdlib.hvoid *thread_function(void *arg) {// 线程执行一些任务后返回一个整数值作为退出状态int *result (int *)malloc(sizeof(int));*result 42;pthread_exit((void *)result);
}int main() {pthread_t thread_id;void *thread_result;// 创建线程if (pthread_create(thread_id, NULL, thread_function, NULL)! 0) {perror(线程创建失败);exit(EXIT_FAILURE);}// 回收线程并获取退出状态if (pthread_join(thread_id, thread_result)! 0) {perror(线程回收失败);exit(EXIT_FAILURE);}// 输出线程的退出状态printf(线程退出状态%d\n, *(int *)thread_result);free(thread_result);printf(主线程继续执行\n);return 0;
} 五、线程取消
pthread_cancel 函数用于请求取消一个线程的执行但线程必须处于可取消状态并且能够响应取消请求线程默认是可取消的但有些情况下可能需要修改线程的可取消性状态。
函数原型int pthread_cancel(pthread_t thread);
示例代码
#include stdio.h
#include pthread.h
#include stdlib.h
#include unistd.hvoid *thread_function(void *arg) {// 线程执行一个循环每隔一秒打印一次信息for (int i 0; i 10; i) {printf(线程运行中...\n);sleep(1);}pthread_exit(NULL);
}int main() {pthread_t thread_id;// 创建线程if (pthread_create(thread_id, NULL, thread_function, NULL)! 0) {perror(线程创建失败);exit(EXIT_FAILURE);}// 主线程睡眠 5 秒后尝试取消子线程sleep(5);if (pthread_cancel(thread_id)! 0) {perror(线程取消失败);exit(EXIT_FAILURE);}// 回收线程即使线程被取消也应该进行回收以确保资源释放pthread_join(thread_id, NULL);printf(主线程继续执行\n);return 0;
}
在上述代码中主线程创建了一个子线程后睡眠 5 秒然后调用 pthread_cancel 尝试取消子线程的执行。子线程在执行过程中如果被成功取消会立即终止然后主线程通过 pthread_join 回收子线程资源。 六、线程分离
线程分离是将线程设置为脱离状态这样线程结束后其资源会自动被系统回收而不需要其他线程调用 pthread_join 来回收。
函数原型int pthread_detach(pthread_t thread);
示例代码
#include stdio.h
#include pthread.h
#include stdlib.hvoid *thread_function(void *arg) {// 线程执行一些任务后自动终止由于被分离不需要其他线程回收printf(线程执行任务后将自动释放资源\n);pthread_exit(NULL);
}int main() {pthread_t thread_id;// 创建线程if (pthread_create(thread_id, NULL, thread_function, NULL)! 0) {perror(线程创建失败);exit(EXIT_FAILURE);}// 分离线程if (pthread_detach(thread_id)! 0) {perror(线程分离失败);exit(EXIT_FAILURE);}// 主线程继续执行其他任务无需等待被分离的线程printf(主线程继续执行无需等待子线程\n);return 0;
}
在这个例子中创建线程后立即调用 pthread_detach 将线程设置为分离状态线程执行完任务后会自动释放资源主线程无需调用 pthread_join 等待其结束。 七、线程安全
线程安全是指多个线程同时访问共享资源时不会产生数据竞争和不一致的问题。实现线程安全通常需要使用同步机制如互斥锁、自旋锁、读写锁、条件变量等。
以下是一个使用互斥锁实现线程安全的示例多个线程对一个共享变量进行自增操作
#include stdio.h
#include pthread.h
#include stdlib.h
#include unistd.h// 共享变量
int shared_variable 0;
// 互斥锁
pthread_mutex_t mutex;void *thread_function(void *arg) {for (int i 0; i 10000; i) {// 加锁保护共享资源pthread_mutex_lock(mutex);shared_variable;// 解锁pthread_mutex_unlock(mutex);}pthread_exit(NULL);
}int main() {pthread_t thread1, thread2;// 初始化互斥锁pthread_mutex_init(mutex, NULL);// 创建两个线程if (pthread_create(thread1, NULL, thread_function, NULL)! 0) {perror(线程 1 创建失败);exit(EXIT_FAILURE);}if (pthread_create(thread2, NULL, thread_function, NULL)! 0) {perror(线程 2 创建失败);exit(EXIT_FAILURE);}// 等待线程结束pthread_join(thread1, NULL);pthread_join(thread2, NULL);// 销毁互斥锁pthread_mutex_destroy(mutex);printf(共享变量最终值%d\n, shared_variable);return 0;
}
在上述代码中两个线程并发地对 shared_variable 进行自增操作。通过使用互斥锁 mutex每次只有一个线程能够进入临界区pthread_mutex_lock 和 pthread_mutex_unlock 之间的代码段对共享变量进行操作从而保证了数据的一致性和线程安全。如果没有互斥锁的保护多个线程同时对共享变量进行读写操作可能会导致数据竞争和错误的结果。