一、线程概述
线程(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
微信扫一扫
支付宝扫一扫