一、线程概述
线程(Thread)是程序执行流的最小单位,它是进程内的一个执行单元。一个进程可以有多个线程,每个线程都可以运行在单独的CPU上。与进程不同,线程共享进程内的一些资源,如内存、文件等。
线程的创建和销毁比进程要方便快捷,因为它们不需要分配独立的地址空间。因此,线程适合于需要高并发的场景,在网络编程、多媒体应用、数据库等应用中都有非常广泛的应用。
二、线程的创建
在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 是指向函数的指针,这个函数是线程运行的起点;arg 是传递给线程的参数,可以是单个变量、结构体或指针。
下面的代码演示了一个简单的线程创建过程:
#include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { printf("Thread running\n"); pthread_exit(NULL); } int main() { pthread_t thread; pthread_create(&thread, NULL, thread_func, NULL); pthread_join(thread, NULL); return 0; }
在这个例子中,线程运行的起点是 thread_func 函数,在该函数内部打印字符串 “Thread running”。在主函数中,调用 pthread_create 创建线程并传入 thread_func 函数,等待线程执行完成后,调用 pthread_join 函数进行回收。
三、线程同步
在多线程环境下,由于多个线程可以同时访问共享资源,因此需要同步操作以避免冲突。
Linux提供了多种同步机制,下面介绍其中两种:互斥锁和条件变量。
互斥锁
互斥锁(mutex)可以用来保证共享资源的互斥访问。当一个线程获取了互斥锁,其他线程需要等待它释放锁后才能执行相应的操作。Linux下的互斥锁实现在pthread.h头文件中,它的主要函数包括:
- pthread_mutex_init 初始化互斥锁
- pthread_mutex_destroy 销毁互斥锁
- pthread_mutex_lock 获取互斥锁
- pthread_mutex_unlock 释放互斥锁
下面是一个使用互斥锁进行同步的例子:
#include <pthread.h> #include <stdio.h> pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int counter = 0; void *thread_func(void *arg) { pthread_mutex_lock(&lock); counter++; printf("Thread ID: %d incremented counter to %d\n", (int)pthread_self(), counter); pthread_mutex_unlock(&lock); pthread_exit(NULL); } int main() { pthread_t threads[10]; for(int i = 0; i < 10; i++) { pthread_create(&threads[i], NULL, thread_func, NULL); } for(int i = 0; i < 10; i++) { pthread_join(threads[i], NULL); } printf("Final value of counter is %d\n", counter); return 0; }
在这个例子中,10个线程共享变量counter,每个线程执行后将counter加1,并打印当前线程的ID和counter的值。由于多线程环境下,对共享变量的操作需要同步,因此在每个线程函数内部使用pthread_mutex_lock和pthread_mutex_unlock进行互斥访问。
条件变量
条件变量(condition variable)是一种同步机制,它能够使一个线程等待另一个线程的通知。线程在条件变量上等待,直到另一个线程使用pthread_cond_signal或pthread_cond_broadcast函数通知它可以继续执行。Linux下的条件变量实现在pthread.h头文件中,它的主要函数包括:
- pthread_cond_init 初始化条件变量
- pthread_cond_destroy 销毁条件变量
- pthread_cond_wait 等待条件变量
- pthread_cond_signal 唤醒一个线程
- pthread_cond_broadcast 唤醒所有线程
下面是一个使用条件变量进行同步的例子:
#include <pthread.h> #include <stdio.h> pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int waiting = 1; void *thread_func(void *arg) { pthread_mutex_lock(&lock); while(waiting) { pthread_cond_wait(&cond, &lock); } printf("Thread ID: %d continuing...\n", (int)pthread_self()); pthread_mutex_unlock(&lock); pthread_exit(NULL); } int main() { pthread_t threads[5]; for(int i = 0; i < 5; i++) { pthread_create(&threads[i], NULL, thread_func, NULL); } sleep(1); printf("Wake up threads ...\n"); pthread_mutex_lock(&lock); waiting = 0; pthread_cond_broadcast(&cond); pthread_mutex_unlock(&lock); for(int i = 0; i < 5; i++) { pthread_join(threads[i], NULL); } return 0; }
在这个例子中,5个线程在条件变量上等待,直到主线程调用pthread_cond_broadcast函数释放条件变量并唤醒它们。线程运行的起点是thread_func函数,在该函数内部调用pthread_cond_wait等待条件变量,在条件变量被唤醒后,线程继续执行并打印当前线程的ID。
四、线程的销毁
在不需要某个线程继续执行的时候,需要销毁它以释放内存等资源。Linux下,使用pthread_cancel函数可以向一个线程发送取消请求,这个请求是异步执行的,即立即返回,线程本身仍然继续执行。另外,还可以使用pthread_join函数等待线程执行完成后回收它的资源。
下面是一个使用pthread_cancel函数取消线程的例子:
#include <pthread.h> #include <stdio.h> void *thread_func(void *arg) { int i = 0; while(1) { printf("Thread ID: %d count %d\n", (int)pthread_self(), i++); } pthread_exit(NULL); } int main() { pthread_t thread; pthread_create(&thread, NULL, thread_func, NULL); sleep(3); pthread_cancel(thread); pthread_join(thread, NULL); printf("Thread canceled\n"); return 0; }
在这个例子中,创建了一个线程,不断循环打印当前线程ID和计数器的值。在主程序中,通过调用pthread_cancel函数向线程发送取消请求,并使用pthread_join函数等待线程完成后回收资源。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/205875.html