Linux多核与线程
在现代操作系统中,Linux凭借其开源和灵活的特性成为了广泛应用的操作系统之一,特别是在多核处理器日益普及的背景下,Linux的多线程编程显得尤为重要,本文将探讨Linux环境下多线程的基础知识、创建与管理、资源同步问题以及线程亲和性等内容,并通过代码示例进行详细说明。
一、线程的基本概念
在现代操作系统中,进程是系统资源分配的最小单位,而线程是CPU调度的最小单位,一个进程可以包含多个线程,这些线程共享进程的资源(如内存地址空间、文件描述符等),但每个线程都有自己的栈、寄存器和本地变量,多线程编程通过在一个进程中创建多个线程,使得这些线程可以并发执行,从而提高程序的执行效率。
优点:
1、资源共享:同一进程的线程共享内存空间、文件描述符等资源,线程间通信更便捷。
2、经济高效:线程的创建、销毁和切换开销通常比进程小。
3、并发执行:多线程能充分利用多核处理器,提高CPU利用率。
二、线程的创建与管理
在Linux系统中,我们通常使用POSIX线程库(pthread库)来创建和管理线程,主要函数包括pthread_create()
创建一个新的线程,pthread_join()
等待线程结束,pthread_exit()
结束当前线程等。
示例代码:线程的创建和销毁
#include <pthread.h> #include <stdio.h> #include <stdlib.h> void* thread_function(void* arg) { printf("Hello from the thread! "); return NULL; } int main() { pthread_t my_thread; int res = pthread_create(&my_thread, NULL, thread_function, NULL); if (res != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } // 等待线程结束 pthread_join(my_thread, NULL); return 0; }
上述代码创建了一个简单的线程,该线程打印一条消息然后结束,主线程等待子线程结束后再结束。
三、资源同步问题
多线程编程中,多个线程可能同时访问同一资源,如果处理不当,可能会导致数据不一致或其他不可预知的结果,我们需要一些同步和互斥机制来确保数据的一致性和准确性。
1. 互斥锁(Mutex)
互斥锁是一种最常用的线程同步机制,它确保一次只有一个线程可以访问共享资源,在访问共享资源前,线程需要获取锁,如果锁被占用,线程将阻塞,直到锁被释放。
#include <pthread.h> #include <stdio.h> pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; void* thread_function(void* arg) { pthread_mutex_lock(&my_mutex); // 访问共享资源 printf("Thread %ld ", pthread_self()); pthread_mutex_unlock(&my_mutex); return NULL; } int main() { pthread_t threads[5]; for (int i = 0; i < 5; i++) { pthread_create(&threads[i], NULL, thread_function, NULL); } for (int i = 0; i < 5; i++) { pthread_join(threads[i], NULL); } return 0; }
2. 信号量(Semaphore)
信号量是一种用于保护对共享资源访问的同步原语,信号量维护一个计数器,表示可用的资源数量,线程在访问共享资源前,需要获取信号量。
#include <pthread.h> #include <semaphore.h> #include <stdio.h> sem_t my_semaphore; void* thread_function(void* arg) { sem_wait(&my_semaphore); // 访问共享资源 printf("Thread %ld ", pthread_self()); sem_post(&my_semaphore); return NULL; } int main() { sem_init(&my_semaphore, 0, 1); // 初始化信号量,初始值为1 pthread_t threads[5]; for (int i = 0; i < 5; i++) { pthread_create(&threads[i], NULL, thread_function, NULL); } for (int i = 0; i < 5; i++) { pthread_join(threads[i], NULL); } sem_destroy(&my_semaphore); // 销毁信号量 return 0; }
3. 条件变量(Condition Variable)
条件变量用于在多线程之间同步数据的访问,一个线程可以在条件变量上等待,直到另一个线程通知它某个条件已经满足。
#include <pthread.h> #include <stdio.h> pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER; int shared_data = 0; void* producer_function(void* arg) { pthread_mutex_lock(&my_mutex); shared_data = 42; // 修改共享资源 pthread_cond_signal(&my_condition); // 发送信号通知等待的线程 pthread_mutex_unlock(&my_mutex); return NULL; } void* consumer_function(void* arg) { pthread_mutex_lock(&my_mutex); while (shared_data == 0) { // 等待条件满足 pthread_cond_wait(&my_condition, &my_mutex); } printf("Consumer: %d ", shared_data); // 处理共享资源 pthread_mutex_unlock(&my_mutex); return NULL; } int main() { pthread_t producer_thread, consumer_thread; pthread_create(&producer_thread, NULL, producer_function, NULL); pthread_create(&consumer_thread, NULL, consumer_function, NULL); pthread_join(producer_thread, NULL); pthread_join(consumer_thread, NULL); return 0; }
四、线程亲和性设置
在Linux下,将不同线程绑定到不同的核心上可以通过pthread_setaffinity_np()
函数实现,这样可以提高多线程程序的性能,特别是在多核处理器上运行时,线程亲和性设置可以确保特定线程在特定的核心上运行,从而减少上下文切换和缓存失效带来的性能损失。
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <sched.h> inline int set_cpu(int i) { cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(i,&mask); printf("thread %u, i = %d ", pthread_self(), i); if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask)) { fprintf(stderr, "pthread_setaffinity_np erro "); return -1; } return 0; } void *thread_ip_bitmap_set(void *p) { uint32_t i, ip; struct id_ipmap *entry; thread_info_t *info = (thread_info_t *)p; if(set_cpu(info->id)) { return NULL; } printf("info->id = %d; info->start = %d; info->end = %d, sub = %d ", info->id, info->start, info->end, info->start info->end); for (i = info->start; i < info->end; ++i) { entry = &ipmap_queue[i]; for (ip = entry->ip_start; ip < entry->ip_end; ip++) { ip_bitmap_set(adns_htobe32(ip), entry->id); } } printf("info->id = %d finished ", info->id); return NULL; } int main() { for(thread_index=0; thread_index < 10; thread_index++) pthread_create(&thread_id[thread_index],NULL, thread_ip_bitmap_set, &thread_info[thread_index]); }
本文详细解析了Linux操作系统中的多线程编程,包括基本概念、线程的创建与管理、同步与互斥、线程间通信等方面,并给出了一系列示例代码来帮助理解,多线程编程能够极大提高程序的执行效率,但也需要我们注意数据的一致性、线程的同步等问题,在实际编程过程中,可以根据具体需求选择合适的同步机制和通信方式,以达到最佳的性能表现。
到此,以上就是小编对于“linux 多核 线程”的问题就介绍到这了,希望介绍的几点解答对大家有用,有任何问题和不懂的,欢迎各位朋友在评论区讨论,给我留言。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1289641.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复