舞动的线程轨迹:编织诗意的Linux多线程之旅

0. Linux 线程编程常用函数汇总

函数说明参数返回值
pthread_create创建新线程- pthread_t *thread: 新线程的标识符- pthread_t: 成功,NULL: 失败
- const pthread_attr_t *attr: 线程属性,默认为NULL
- void *(*start_routine)(void *): 线程执行的函数
- void *arg: 传递给线程执行函数的参数
pthread_join主线程等待子线程结束- pthread_t thread: 目标线程的标识符- 成功:0,失败:错误代码
- void **value_ptr: 用于存储目标线程返回值的地址
pthread_exit线程结束并返回值- void *value_ptr: 线程的返回值
pthread_self获取当前线程IDpthread_t: 当前线程的标识符
pthread_mutex_init初始化互斥锁- pthread_mutex_t *mutex: 互斥锁的指针- 成功:0,失败:错误代码
- const pthread_mutexattr_t *attr: 互斥锁属性,默认为NULL
pthread_mutex_destroy销毁互斥锁- pthread_mutex_t *mutex: 互斥锁的指针- 成功:0,失败:错误代码
pthread_mutex_lock锁定互斥锁- pthread_mutex_t *mutex: 互斥锁的指针- 成功:0,失败:错误代码
pthread_mutex_unlock解锁互斥锁- pthread_mutex_t *mutex: 互斥锁的指针- 成功:0,失败:错误代码
pthread_cond_init初始化条件变量- pthread_cond_t *cond: 条件变量的指针- 成功:0,失败:错误代码
- const pthread_condattr_t *attr: 条件变量属性,默认为NULL
pthread_cond_destroy销毁条件变量- pthread_cond_t *cond: 条件变量的指针- 成功:0,失败:错误代码
pthread_cond_wait等待条件变量- pthread_cond_t *cond: 条件变量的指针- 成功:0,失败:错误代码
- pthread_mutex_t *mutex: 与条件变量相关联的互斥锁的指针
pthread_cond_signal唤醒等待条件变量的一个线程- pthread_cond_t *cond: 条件变量的指针- 成功:0,失败:错误代码
pthread_cond_broadcast唤醒等待条件变量的所有线程- pthread_cond_t *cond: 条件变量的指针- 成功:0,失败:错误代码
pthread_rwlock_init初始化读写锁- pthread_rwlock_t *rwlock: 读写锁的指针- 成功:0,失败:错误代码
- const pthread_rwlockattr_t *attr: 读写锁属性,默认为NULL
pthread_rwlock_destroy销毁读写锁- pthread_rwlock_t *rwlock: 读写锁的指针- 成功:0,失败:错误代码
pthread_rwlock_rdlock读锁定读写锁- pthread_rwlock_t *rwlock: 读写锁的指针- 成功:0,失败:错误代码
pthread_rwlock_wrlock写锁定读写锁- pthread_rwlock_t *rwlock: 读写锁的指针- 成功:0,失败:错误代码
pthread_rwlock_unlock解锁读写锁- pthread_rwlock_t *rwlock: 读写锁的指针- 成功:0,失败:错误代码

1. 简介

  • 1.1 什么是线程

    • 线程是操作系统调度的最小执行单位,是进程的一部分,共享进程的资源。线程间通过共享内存进行通信。
    • 示例代码:
      #include <pthread.h>
      #include <stdio.h>
      
      void *thread_function(void *arg) {
          // 线程执行的函数体
          return NULL;
      }
      
      int main() {
          pthread_t my_thread;
          pthread_create(&my_thread, NULL, thread_function, NULL);                   
      
          // 主线程继续执行其他任务
      
          pthread_join(my_thread, NULL); // 等待线程结束
      
          return 0;
      }
      
  • 1.2 多线程的优势

    • 提高程序并发性,充分利用多核处理器的性能。
    • 适用于I/O密集型任务,避免阻塞整个进程。
  • 1.3 线程与进程的区别

    • 进程是独立的执行单元,有独立的地址空间和资源,进程间通信较为复杂。
    • 线程是进程的子任务,共享进程的地址空间和资源,通过共享内存等机制进行通信。

2. 基础概念

  • 2.1 线程的创建和终止
    // 示例代码
    #include <pthread.h>
    #include <stdio.h>
    
    void *thread_function(void *arg) {
        // 线程执行的函数体
        return NULL;
    }
    
    int main() {
        pthread_t my_thread;
        pthread_create(&my_thread, NULL, thread_function, NULL);
    
        // 主线程继续执行其他任务
    
        pthread_join(my_thread, NULL); // 等待线程结束
    
        return 0;
    }
    
  • 2.2 互斥锁和条件变量
    // 示例代码
    #include <pthread.h>
    #include <stdio.h>
    
    pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;
    
    void *thread_function(void *arg) {
        pthread_mutex_lock(&my_mutex);
        
        // 线程执行的任务
    
        pthread_cond_signal(&my_condition);
        pthread_mutex_unlock(&my_mutex);
    
        return NULL;
    }
    
    int main() {
        pthread_t my_thread;
        pthread_create(&my_thread, NULL, thread_function, NULL);
    
        pthread_mutex_lock(&my_mutex);
    
        // 主线程等待条件变量
        pthread_cond_wait(&my_condition, &my_mutex);
    
        pthread_mutex_unlock(&my_mutex);
    
        return 0;
    }
    

3. 进阶主题

  • 3.1 线程同步

    • 3.1.1 信号量

      • 信号量是一种用于线程同步的机制,通过计数器来控制对资源的访问。
      • 示例代码:
        #include <pthread.h>
        #include <semaphore.h>
        #include <stdio.h>
        
        sem_t my_semaphore;
        
        void *thread_function(void *arg) {
            sem_wait(&my_semaphore); // 等待信号量
            
            // 线程执行的任务
        
            sem_post(&my_semaphore); // 释放信号量
            return NULL;
        }
        
        int main() {
            sem_init(&my_semaphore, 0, 1); // 初始化信号量
        
            pthread_t my_thread;
            pthread_create(&my_thread, NULL, thread_function, NULL); 
        
            // 主线程继续执行其他任务
        
            pthread_join(my_thread, NULL); // 等待线程结束
        
            sem_destroy(&my_semaphore); // 销毁信号量
        
            return 0;
        }
        
    • 3.1.2 屏障

      • 屏障用于协调多个线程的执行,在所有线程都到达屏障点时,才能继续执行。
      • 示例代码:
        #include <pthread.h>
        #include <stdio.h>
        
        pthread_barrier_t my_barrier;
        
        void *thread_function(void *arg) {
            // 线程执行的任务
        
            pthread_barrier_wait(&my_barrier); // 等待其他线程到达屏障点
        
            // 屏障后继续执行任务
        
            return NULL;
        }
        
        int main() {
            pthread_barrier_init(&my_barrier, NULL, NUM_THREADS); // 初始化屏障
        
            pthread_t my_thread[NUM_THREADS];
            for (int i = 0; i < NUM_THREADS; ++i) {
                pthread_create(&my_thread[i], NULL, thread_function, NULL);
            }
        
            // 主线程继续执行其他任务
        
            for (int i = 0; i < NUM_THREADS; ++i) {
                pthread_join(my_thread[i], NULL); // 等待线程结束
            }
        
            pthread_barrier_destroy(&my_barrier); // 销毁屏障
        
            return 0;
        }
        
  • 3.2 线程池的实现

    // 示例代码
    #include <pthread.h>
    #include <stdio.h>
    
    #define THREAD_POOL_SIZE 5
    
    pthread_t thread_pool[THREAD_POOL_SIZE];
    
    void *thread_function(void *arg) {
        // 线程池中线程的执行函数
        return NULL;
    }
    
    int main() {
        for (int i = 0; i < THREAD_POOL_SIZE; ++i) {
            pthread_create(&thread_pool[i], NULL, thread_function, NULL);      
        }
    
        // 主线程继续执行其他任务
    
        for (int i = 0; i < THREAD_POOL_SIZE; ++i) {
            pthread_join(thread_pool[i], NULL); // 等待线程结束
        }
    
        return 0;
    }
    

4. 调试与性能优化

  • 4.1 GDB调试多线程程序

    • GDB是GNU调试器,用于调试程序。在调试多线程程序时,可以使用以下命令行进行调试:
      gdb ./your_program
      (gdb) target exec ./your_program
      (gdb) break your_breakpoint
      (gdb) run
      (gdb) thread apply all bt
      
      • break:设置断点
      • run:运行程序
      • thread apply all bt:打印所有线程的调用堆栈
  • 4.2 线程安全性和性能优化技巧

    • 线程安全性:

      • 使用互斥锁(Mutex)来保护共享资源,避免多线程同时访问导致数据不一致。
      • 注意避免死锁,使用适当的加锁顺序。
      • 使用条件变量(Condition Variable)实现线程间的协同操作。
    • 性能优化技巧:

      • 减小锁的粒度,尽量缩小临界区的范围。
      • 使用读写锁(Read-Write Lock)实现读写分离,提高并发性能。
      • 考虑使用无锁数据结构,如原子操作等,减小锁的开销。
      • 合理使用线程池来管理线程,减少线程创建销毁的开销。
      • 使用性能分析工具,如perf等,定位性能瓶颈并进行优化。
    // 示例代码:使用读写锁进行读写分离
    #include <pthread.h>
    #include <stdio.h>
    
    pthread_rwlock_t my_rwlock;
    
    void *read_thread(void *arg) {
        pthread_rwlock_rdlock(&my_rwlock);
    
        // 读操作
    
        pthread_rwlock_unlock(&my_rwlock);
    
        return NULL;
    }
    
    void *write_thread(void *arg) {
        pthread_rwlock_wrlock(&my_rwlock);
    
        // 写操作
    
        pthread_rwlock_unlock(&my_rwlock);
    
        return NULL;
    }
    
    int main() {
        pthread_rwlock_init(&my_rwlock, NULL); // 初始化读写锁
    
        // 创建读线程和写线程
    
        pthread_rwlock_destroy(&my_rwlock); // 销毁读写锁
    
        return 0;
    }
    

5. 实际应用与案例分析

  • 5.1 多线程网络编程*(这里看不懂没关系,网络编程后面还会详细讲到)*

    • 在多线程网络编程中,可以利用多线程处理并发的网络请求,提高服务器的响应能力。使用线程池管理线程,避免频繁创建销毁线程的开销。
    • 示例代码:
      #include <pthread.h>
      #include <stdio.h>
      
      #define THREAD_POOL_SIZE 5
      
      pthread_t thread_pool[THREAD_POOL_SIZE];
      
      void *thread_function(void *arg) {
          // 网络请求处理任务
      
          return NULL;
      }
      
      int main() {
          for (int i = 0; i < THREAD_POOL_SIZE; ++i) {
              pthread_create(&thread_pool[i], NULL, thread_function, NULL);                              
          }
      
          // 主线程继续执行其他任务
      
          for (int i = 0; i < THREAD_POOL_SIZE; ++i) {
              pthread_join(thread_pool[i], NULL); // 等待线程结束
          }
      
          return 0;
      }
      
  • 5.2 并行算法与数据结构

    • 并行排序算法示例:
      #include <pthread.h>
      #include <stdio.h>
      #include <stdlib.h>
      
      #define ARRAY_SIZE 1000000
      #define NUM_THREADS 4
      
      int array[ARRAY_SIZE];
      
      typedef struct {
          int start;
          int end;
      } ThreadData;
      
      void *parallel_merge_sort(void *arg) {
          ThreadData *data = (ThreadData *)arg;
      
          // 在[start, end]范围内进行归并排序
      
          return NULL;
      }
      
      int main() {
          // 初始化数组
      
          pthread_t threads[NUM_THREADS];
          ThreadData thread_data[NUM_THREADS];
      
          // 划分数组,每个线程处理一部分
      
          for (int i = 0; i < NUM_THREADS; ++i) {
              pthread_create(&threads[i], NULL, parallel_merge_sort, &thread_data[i]);
          }
      
          // 主线程等待所有线程结束
      
          for (int i = 0; i < NUM_THREADS; ++i) {
              pthread_join(threads[i], NULL);
          }
      
          // 合并排序结果
      
          return 0;
      }
      
  • 5.3 实际案例分析与解决方案

    • 示例代码:(假设存在一个需要解决的线程安全问题)
      #include <pthread.h>
      #include <stdio.h>
      
      int shared_variable = 0;
      pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
      
      void *thread_function(void *arg) {
          for (int i = 0; i < 100000; ++i) {
              pthread_mutex_lock(&my_mutex);
      
              // 线程执行可能存在的竞态条件操作
              shared_variable++;
      
              pthread_mutex_unlock(&my_mutex);
          }
      
          return NULL;
      }
      
      int main() {
          pthread_t my_thread1, my_thread2;
          pthread_create(&my_thread1, NULL, thread_function, NULL);
          pthread_create(&my_thread2, NULL, thread_function, NULL);
      
          pthread_join(my_thread1, NULL);
          pthread_join(my_thread2, NULL);
      
          printf("Final value of shared_variable: %d\n", shared_variable);
      
          return 0;
      }
      

6. 参考资料

大家有任何不懂的都可以留言讨论,欢迎评论!

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值