12.linux笔记:线程

12.linux笔记:线程 1.什么是线程线程指的是进程当中的执行流。进程程序放到内存里的可执行实例进程是程序的一个实例。同一个程序若多次读取到内存中则变成多个独立的进程。内存有地址内存中的每个进程内部都有虚拟独立的地址空间。这样在进程里面就可以用虚拟地址来访问进程内的地方。进程是程序执行的完整单位进程间通信IPC。一个进程里有好多线程每个线程里有程序计数器、寄存器、堆栈、全局变量。线程是并行的最小单位cpu为每个线程分配虚拟cpu不需要时间片轮转实现真正并行。2.POSIX标准的线程POSIX标准就是一套规范方便移植。什么是POSIX 线程POSIX.1 标准的线程通常称为POSIX 线程或PthreadsPOSIX指定每个线程独有属性线程ID、errno变量perror会打印对应线程的errno的错误信息POSIX.1 要求线程共享一系列属性线程共享相同的全局内存数据段和堆段每个线程都有自己的堆栈自动变量各种标识符进程ID、父进程 ID、进程组 ID 和会话 ID等各种资源控制终端、打开的文件描述符等进程的属性或设置信号处置、文件权限掩码umaskPthreads 函数Linux下的POSIX threads线程已淘汰原始的linux下没有进程只有轻量级进程Linux thread3.线程的创建主线程main函数开始的地方是主线程。每个进程在创建时都会自动生成一个线程这就是主线程。它负责执行程序代码从main函数开始是这个工厂里的第一条、也是最重要的一条生产线。主线程里用pthread_create创建的线程叫附加线程附加线程会受到主线程执行流的影响。主线程结束所有其他附加线程也会结束。#include pthread.h #include stdio.h #include unistd.h void *func (void*arg){ printf(helloworld\n); return NULL; } int main(int argc, const char *argv[]) { pthread_t tid; pthread_create(tid,NULL,func,NULL); // sleep(1); pthread_join(tid,NULL); return 0; }pthread_join)相当于进程概念中的waitpthread_create()函数1.第一个参数thread线程号ID用pthread_t 创建线程ID的内存。pthread_create创建好线程以后会把线程ID放到pthread_t创建的ID内存里。2.第二个参数attr线程的属性如果传NULL就会采用默认属性3.第三个参数是个函数指针函数名退化成的指针指向一个返回值和参数都是void*的函数。用来把各种函数数据通过指针传给线程。4.第四个参数第三个参数的函数的参数。也就是start_routine的参数pthread_create函数如果创建失败不会直接设置errno所以如果少了 errno retperror输出的是errno默认的内容。pthread_create底层会调用clone接口。clone能够设置errno。实例1资源耗尽无法继续创建线程#include pthread.h #include stdio.h #include unistd.h #include errno.h void *func (void*arg){ //printf(helloworld\n); return NULL; } int main(int argc, const char *argv[]) { int ret 0; pthread_t tid; while(ret 0){ ret pthread_create(tid,NULL,func,NULL); } errno ret; perror(pthread_create); // sleep(1); // pthread_join(tid,NULL); return 0; }实例2创建失败的错误处理#include pthread.h #include stdio.h #include unistd.h #include errno.h #include stdlib.h void *func (void*arg){ printf(helloworld\n); return NULL; } int main(int argc, const char *argv[]) { int ret 0; pthread_t tid; ret pthread_create(tid,NULL,func,NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } // sleep(1); pthread_join(tid,NULL); return 0; }#include pthread.h #include stdio.h #include unistd.h #include stdlib.h #include string.h void *func (void*arg){ printf(helloworld\n); return NULL; } int main(int argc, const char *argv[]) { int ret 0; pthread_t tid; ret pthread_create(tid,NULL,func,NULL); //if(ret ! 0){ char *str strerror(ret); printf(%s\n,str); // exit(EXIT_FAILURE); //} // sleep(1); pthread_join(tid,NULL); return 0; }#include pthread.h #include stdio.h #include unistd.h #include stdlib.h #include string.h void *func (void*arg){ printf(helloworld\n); pthread_exit(NULL); //return NULL; } int main(int argc, const char *argv[]) { int ret 0; pthread_t tid; ret pthread_create(tid,NULL,func,NULL); if(ret ! 0){ char *str strerror(ret); fprintf(stderr,pthread creat:%s\n,str); exit(EXIT_FAILURE); } // sleep(1); ret pthread_join(tid,NULL); if(ret ! 0){ errno ret; perror(pthread join); exit(EXIT_FAILURE); } return 0; }pthread_create返回0成功非0为失败不是小于0。pthread_create()不会设置errno这个全局变量Resource temporaril unavailable 资源咱不可用Cannot allocate memory无法分配内存4.线程的终止与分离属性return、pthread_exit、exit区别调用pthread_exit()指定一个退出状态值从start_routine()的 return语句 返回 相当于调用pthread_exit()被取消pthread_cancel()进程被终止将导致所有线程终止#include pthread.h #include stdio.h #include unistd.h void* child_thread(void* arg) { while(1) { printf(子线程正在运行...\n); sleep(1); } return NULL; } int main() { pthread_t tid; pthread_create(tid, NULL, child_thread, NULL); sleep(2); // 情况1: return 0; → 进程终止子线程被强制结束 // 情况2: pthread_exit(NULL); → 仅主线程结束子线程继续运行 pthread_exit(NULL); // 子线程会继续运行 // return 0; // 子线程会立即终止 }#include pthread.h #include stdio.h #include stdlib.h #include errno.h #include unistd.h void *func (void *arg) { printf(Hello thread!\n); sleep(10); printf(thread done.\n); //由于线程被主线程取消所以这里不会被执行 pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid; int ret pthread_create(tid, NULL, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } sleep(1); pthread_cancel(tid); printf(tid%lu\n, tid); pthread_join(tid, NULL); return 0; }exit不管在哪个线程都会终止整个进程。pthread_exit不管在主/子线程都只会终止那一个线程线程的执行顺序不确定#include pthread.h #include stdio.h #include stdlib.h #include errno.h #include unistd.h void *func (void *arg) { printf(id %d\n,(int)(long)arg); pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid[10]; int id[10]; int ret; for(int i 0; i 10;i){ id[i] i; ret pthread_create(tid[i], NULL, func, (void*)(long)id[i]); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } } for(int i 0; i 10;i){ ret pthread_join(tid[i], NULL); if(ret ! 0){ errno ret; perror(pthread_join); exit(EXIT_FAILURE); } } return 0; }线程的分离属性线程的执行顺序是不确定的线程是可连接的或者是分离的可连接的调用pthread_join()等待线程终止并获取退出状态分离的线程其资源会自动放回系统pthread_detachpthread_self()设置线程为分离属性#include pthread.h #include stdio.h #include stdlib.h #include errno.h #include unistd.h void *func (void *arg) { pthread_detach(pthread_self()); //设置线程为分离属性 printf(detach thread.\n); pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid; int ret pthread_create(tid, NULL, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } // pthread_detach(tid); //也可以在主线程当中设置创建线程的分离属性 printf(tid%lu\n, tid); sleep(1); return 0; }pthread_attr_t attr;pthread_attr_init(attr);pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);#include pthread.h #include stdio.h #include stdlib.h #include errno.h #include signal.h #include unistd.h void *func (void *arg) { printf(detach thread.\n); pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(attr); pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED); int ret pthread_create(tid, attr, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } pthread_attr_destroy(attr); printf(tid%lu\n, tid); sleep(1); return 0; }pthread“不透明”的数据类型不透明的数据类型属性设置时用特定函数接口来实现pthread_join连接函数连接正常终止的线程#include pthread.h #include stdio.h #include stdlib.h #include errno.h void *func (void *arg) { pthread_exit(thread exit); } int main(int argc, const char *argv[]) { pthread_t tid; int ret pthread_create(tid, NULL, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } void *retval; ret pthread_join(tid, retval); //func返回的字符串的地址被放到retval里 if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } printf(retval:%s\n, (char *)retval); retval是void*指针内容是func返回的字符串的地址 return 0; }#include pthread.h #include stdio.h #include stdlib.h #include errno.h static int a 10; void *func (void *arg) { int *p a; pthread_exit(p); } int main(int argc, const char *argv[]) { pthread_t tid; int ret pthread_create(tid, NULL, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } void *retval; ret pthread_join(tid, retval); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } printf(retval:%d\n, *(int *)retval); return 0; }这里解释下pthread_join的第二个参数pthread_join是把线程的返回值给二级指针指向的内存也就是一级指针。把线程返回值赋给一级指针。上面的例子retval p;连接被取消的线程#include pthread.h #include stdio.h #include stdlib.h #include errno.h #include unistd.h static int a 10; void *func (void *arg) { sleep(100); int *p a; pthread_exit(p); } int main(int argc, const char *argv[]) { pthread_t tid; int ret pthread_create(tid, NULL, func, NULL); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } sleep(1); pthread cancel(tid); void *retval; ret pthread_join(tid, retval); if(ret ! 0){ errno ret; perror(pthread_create); exit(EXIT_FAILURE); } if(retval PTHREAD_CANCELED){ printf(retval:%d\n,(int)retval); } return 0; }多线程实验一个耗时的算法单线程#include stdio.h #include unistd.h #include stdlib.h #include time.h int main(int argc, const char *argv[]) { unsigned long long a; if(argc ! 2) { fprintf(stderr, Usage %s [loops]\n, argv[0]); exit(EXIT_FAILURE); } if(sscanf(argv[1], %llu, a) ! 1) { fprintf(stderr, loops Invalid.\n); exit(EXIT_FAILURE); } time_t t; time(t); for(unsigned long long i 0; i a; i); time_t t2; time(t2); printf(进程使用了 %ld 秒\n, t2 - t); return 0; }多线程#include stdio.h #include unistd.h #include stdlib.h #include time.h #include pthread.h #include string.h void *ThreadFunc(void *arg) { unsigned long long a *(unsigned long long *)arg; for(unsigned long long i 0; i a; i); pthread_exit(NULL); } int main(int argc, const char *argv[]) { unsigned long long a; if(argc ! 2) { fprintf(stderr, Usage %s [loops]\n, argv[0]); exit(EXIT_FAILURE); } if(sscanf(argv[1], %llu, a) ! 1) { fprintf(stderr, loops Invalid.\n); exit(EXIT_FAILURE); } time_t t; time(t); unsigned long long loops a / 4; pthread_t tid[4] {}; for(int i 0; i 4; i) { int ret pthread_create(tid[i], NULL, ThreadFunc, loops); if(ret ! 0) { fprintf(stderr, pthread_create:%s\n, strerror(ret) ); exit(EXIT_FAILURE); } } for(int i 0; i 4; i) { int ret pthread_join(tid[i], NULL); if(ret ! 0) { fprintf(stderr, pthread_join:%s\n, strerror(ret) ); exit(EXIT_FAILURE); } } time_t t2; time(t2); printf(进程使用了 %ld 秒\n, t2 - t); return 0; }5.线程同步互斥量解决同步问题/* 为突出问题 代码省略了错误处理*/ #include pthread.h #include stdio.h #include stdlib.h static int glob; // 全局变量被所有线程共享 // 线程函数 void *ThreadFunc(void *arg) { int loops *((int *)arg); // 从参数中获取循环次数 int loc, j; for(j 0; j loops; j) { loc glob; // 读取全局变量 或者把这三行改成g;原子操作 loc; // 局部变量自增 glob loc; // 将局部变量的值赋给全局变量 } pthread_exit(NULL); // 线程退出 } int main(int argc, const char *argv[]) { pthread_t tid1, tid2; // 定义两个线程 ID int loops; // 检查命令行参数 if(argc ! 2) { fprintf(stderr, %s [loops]\n, argv[0]); exit(EXIT_FAILURE); } // 从命令行参数中读取循环次数 if( sscanf(argv[1], %d, loops) ! 1) { fprintf(stderr, Invalid loops\n); exit(EXIT_FAILURE); } // 创建两个线程都执行 ThreadFunc 函数 pthread_create(tid1, NULL, ThreadFunc, loops); pthread_create(tid2, NULL, ThreadFunc, loops); // 等待两个线程结束 pthread_join(tid1, NULL); pthread_join(tid2, NULL); // 打印最终的全局变量值 printf(glob %d\n, glob); return 0; }互斥量同一时刻只能让一个线程执行这行代码静态分配的互斥量如果发起pthread_mutex_lock()调用的线程自身之前已然将目标互斥量锁定对于互斥量的默认类型而言可能会产生两种后果—视具体实现而定线程陷入死锁deadlock因试图锁定已为自己所持有的互斥量而遭到阻塞或者调用失败返回EDEADLK错误。在Linux上默认情况下线程会发生死锁。函数pthread_mutex_unlock()将解锁之前已遭调用线程锁定的互斥量。以下行为均属错误对处于未锁定状态的互斥量进行解锁解锁由其他线程锁定的互斥量如果有不止一个线程在等待获取由函数pthread_mutex_unlock()解锁的互斥量则无法判断究竟哪个线程将如愿以偿。临界区加锁和解锁中间的代码叫临界区。临界区访问的资源叫临界资源同一时刻只能由一个线程访问临界资源。销毁互斥量int pthread_mutex_destroymutex函数#include pthread.h #include stdio.h #include stdlib.h #include string.h static int glob; //临界资源 pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; // 静态初始化互斥量 void *ThreadFunc(void *arg) { int loops *((int *)arg); int loc, j; for(j 0; j loops; j) { pthread_mutex_lock(mutex); //加锁与解锁的代码区域被称为 临界区 loc glob; loc; glob loc; pthread_mutex_unlock(mutex); } pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid1, tid2; int loops; if(argc ! 2) { fprintf(stderr, %s [loops]\n, argv[0]); exit(EXIT_FAILURE); } if( sscanf(argv[1], %d, loops) ! 1) { fprintf(stderr, Invalid loops\n); exit(EXIT_FAILURE); } int ret pthread_create(tid1, NULL, ThreadFunc, loops); if(ret ! 0) { fprintf(stderr, pthread_create:%s\n, strerror(ret)); exit(EXIT_FAILURE); } ret pthread_create(tid2, NULL, ThreadFunc, loops); if(ret ! 0) { fprintf(stderr, pthread_create:%s\n, strerror(ret)); exit(EXIT_FAILURE); } ret pthread_join(tid1, NULL); if(ret ! 0) { fprintf(stderr, pthread_join tid1:%s\n, strerror(ret)); exit(EXIT_FAILURE); } ret pthread_join(tid2, NULL); if(ret ! 0) { fprintf(stderr, pthread_join tid2:%s\n, strerror(ret)); exit(EXIT_FAILURE); } printf(glob %d\n, glob); return 0; }使用锁的时候先加锁再解锁不要有其他操作。能使用一把锁就只使用一把锁。如果一定要使用两把锁不要嵌套使用。动态初始化的互斥量/* 为突出问题 代码省略了错误处理*/ #include pthread.h #include stdio.h #include stdlib.h static int glob; struct thread { int loops; pthread_mutex_t mutex; }; // 线程函数 void *ThreadFunc(void *arg) { struct thread *data (struct thread *)arg; // 从参数中获取循环次数 int loc, j; for(j 0; j >/* 为突出问题 代码省略了错误处理 */ #include pthread.h #include stdio.h #include stdlib.h static int glob; int loops; // ✅ 修正英文分号 pthread_mutex_t mutex; // 注意这里是普通变量不是指针 // 线程函数 void *ThreadFunc(void *arg) { int loc, j; int n *((int *)arg); // ✅ 改名避免冲突或用全局 loops for(j 0; j n; j) { // 用局部变量 n 控制循环 pthread_mutex_lock(mutex); glob; pthread_mutex_unlock(mutex); } pthread_exit(NULL); } int main(int argc, const char *argv[]) { pthread_t tid1, tid2; pthread_mutex_init(mutex, NULL); // ✅ 修正传地址 mutex if(argc ! 2) { fprintf(stderr, %s [loops]\n, argv[0]); exit(EXIT_FAILURE); } if(sscanf(argv[1], %d, loops) ! 1) { // ✅ 修正传 loops fprintf(stderr, Invalid loops\n); exit(EXIT_FAILURE); } pthread_create(tid1, NULL, ThreadFunc, loops); pthread_create(tid2, NULL, ThreadFunc, loops); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(mutex); // ✅ 修正传地址 printf(glob %d\n, glob); return 0; }思考如何解决以下代码的数据同步问题#include stdio.h #include stdlib.h #include pthread.h #include unistd.h #include time.h #define NUM_READERS 5 #define NUM_WRITERS 2 int balance 1000; // 初始账户余额 pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; // 读取者线程函数 void* reader(void* arg) { int id *((int*)arg); while (1) { pthread_mutex_lock(mutex); printf(读者 %d: 当前余额为 %d 元\n, id, balance); sleep(2); pthread_mutex_unlock(mutex); sleep(rand() % 3); // 随机休眠 } return NULL; } // 写入者线程函数 void* writer(void* arg) { int id *((int*)arg); while (1) { pthread_mutex_lock(mutex); int amount rand() % 100; // 随机生成一个金额 balance amount; // 修改余额 sleep(2); printf(写者 %d: 存入 %d 元最新余额为 %d 元\n, id, amount, balance); pthread_mutex_unlock(mutex); sleep(rand() % 3); // 随机休眠 } return NULL; } int main() { pthread_t readers[NUM_READERS]; //5个元素 pthread_t writers[NUM_WRITERS]; //2个元素 int reader_ids[NUM_READERS]; //5个元素 int writer_ids[NUM_WRITERS]; //2个元素 srand(time(NULL)); for (int i 0; i NUM_READERS; i) { reader_ids[i] i 1; pthread_create(readers[i], NULL, reader, reader_ids[i]); } for (int i 0; i NUM_WRITERS; i) { writer_ids[i] i 1; pthread_create(writers[i], NULL, writer, writer_ids[i]); } for (int i 0; i NUM_READERS; i) { pthread_join(readers[i], NULL); } for (int i 0; i NUM_WRITERS; i) { pthread_join(writers[i], NULL); } return 0; }如果不加锁读写锁多线程并发的程序不是立刻就能发现数据的同步问题往往运行一段时间才会出现出错原因是数据没有做好同步工作没有做好互斥量。互斥锁写锁独占时读锁也不能访问。#include stdio.h #include stdlib.h #include pthread.h #include unistd.h #include time.h #define NUM_READERS 5 #define NUM_WRITERS 2 int balance 1000; // 初始账户余额 pthread_rwlock_t rwlock; // 读写锁 // 读取者线程函数 void* reader(void* arg) { int id *((int*)arg); while (1) { pthread_rwlock_rdlock(rwlock); // 获取读锁 printf(读者 %d: 当前余额为 %d 元\n, id, balance); pthread_rwlock_unlock(rwlock); // 释放读锁 sleep(rand() % 3); // 随机休眠 } return NULL; } // 写入者线程函数 void* writer(void* arg) { int id *((int*)arg); while (1) { int amount rand() % 100; // 随机生成一个金额 pthread_rwlock_wrlock(rwlock); // 获取写锁 balance amount; // 修改余额 printf(写者 %d: 存入 %d 元最新余额为 %d 元\n, id, amount, balance); pthread_rwlock_unlock(rwlock); // 释放写锁 sleep(rand() % 3); // 随机休眠 } return NULL; } int main() { pthread_t readers[NUM_READERS]; pthread_t writers[NUM_WRITERS]; int reader_ids[NUM_READERS]; int writer_ids[NUM_WRITERS]; srand(time(NULL)); // 初始化随机数种子 // 初始化读写锁 pthread_rwlock_init(rwlock, NULL); // 创建读取者线程 for (int i 0; i NUM_READERS; i) { reader_ids[i] i 1; pthread_create(readers[i], NULL, reader, reader_ids[i]); } // 创建写入者线程 for (int i 0; i NUM_WRITERS; i) { writer_ids[i] i 1; pthread_create(writers[i], NULL, writer, writer_ids[i]); } // 等待读取者线程结束实际上不会结束 for (int i 0; i NUM_READERS; i) { pthread_join(readers[i], NULL); } // 等待写入者线程结束实际上不会结束 for (int i 0; i NUM_WRITERS; i) { pthread_join(writers[i], NULL); } // 销毁读写锁 pthread_rwlock_destroy(rwlock); return 0; }6.条件变量解决生产者与消费者问题通常使用以下几种同步机制信号量Semaphore2.条件变量Condition Variable条件变量通常与互斥锁Mutex结合使用用于线程之间的同步。条件变量允许线程在某个条件不满足时等待而当条件满足时被唤醒。伪代码示例如下#include pthread.h #include semaphore.h #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int count 0; int in 0, out 0; pthread_mutex_t mutex; pthread_cond_t not_full, not_empty; void* producer(void* arg) { while (true) { int item produce_item(); // 生成一个项目 pthread_mutex_lock(mutex); while (count BUFFER_SIZE) { pthread_cond_wait(not_full, mutex); // 缓冲区满时等待 } buffer[in] item; // 将项目放入缓冲区 in (in 1) % BUFFER_SIZE; count; pthread_cond_signal(not_empty); // 通知消费者有新项目 pthread_mutex_unlock(mutex); } return NULL; } void* consumer(void* arg) { while (true) { pthread_mutex_lock(mutex); while (count 0) { pthread_cond_wait(not_empty, mutex); // 缓冲区空时等待 } int item buffer[out]; // 从缓冲区取出项目 out (out 1) % BUFFER_SIZE; count--; pthread_cond_signal(not_full); // 通知生产者缓冲区有空位 pthread_mutex_unlock(mutex); consume_item(item); // 处理项目 } return NULL; }3.队列 使用一个线程安全的队列来管理缓冲区生产者将数据放入队列消费者从队列中取出数据。队列通常内部已经实现了同步机制使用起来更加方便。伪代码示例如下import threading import queue BUFFER_SIZE 10 buffer_queue queue.Queue(BUFFER_SIZE) def producer(): while True: item produce_item() # 生成一个项目 buffer_queue.put(item) # 将项目放入队列 print(fProduced: {item}) def consumer(): while True: item buffer_queue.get() # 从队列取出项目 consume_item(item) # 处理项目 buffer_queue.task_done() print(fConsumed: {item}) # 创建生产者和消费者线程 producer_thread threading.Thread(targetproducer) consumer_thread threading.Thread(targetconsumer) # 启动线程 producer_thread.start() consumer_thread.start() # 等待所有线程完成 producer_thread.join() consumer_thread.join()应用场景生产者与消费者问题在多线程编程中广泛应用于各种场景例如数据处理生产者线程生成数据消费者线程处理数据。任务调度生产者线程生成任务消费者线程执行任务。消息传递生产者线程发送消息消费者线程接收并处理消息。注意事项死锁确保线程不会因为等待条件变量而陷入死锁。通常使用while循环来检查条件而不是if语句。性能避免频繁的线程切换可以通过批量处理数据或使用更高效的同步机制来提高性能。公平性确保生产者和消费者线程之间有合理的调度避免某个线程长时间占用资源。通过以上方法可以有效地解决生产者与消费者问题确保多线程程序的正确性和高效性。什么是条件变量条件变量condition variable 的缩写是一种同步设备条件变量允许一个线程就某个共享变量或其他共享资源的状态变化通知其他线程并让其他线程等待堵塞于这一通知。条件变量是怎样工作的条件变量的使用条件变量是在加锁的基础上再操作的。#include stdio.h #include stdlib.h #include pthread.h #include unistd.h #include time.h //初始化条件变量 pthread_cond_t cond PTHREAD_COND_INITIALIZER; //初始化互斥量 pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; #define NUM_CONSUMER 5 //消费者线程数量 #define NUM_PRODUCER 2 //生产者线程数量 int balance; // 初始账户余额为0 // 消费者线程函数 void *consumer(void* arg) { int id *((int*)arg); while (1) { int amount rand() % 100; // 随机生成一个金额 pthread_mutex_lock(mutex); do { pthread_cond_wait(cond, mutex); //解锁阻塞等待, 收到信号以后再加锁,访问临界资源 } while(balance amount); balance - amount; // 消费 printf([消费者ID:%d]消费 %d 元: 当前余额为 %d 元\n, id, amount, balance); pthread_mutex_unlock(mutex); sleep(rand() % 3); // 随机休眠 } return NULL; } // 生产者线程 void* producer(void* arg) { int id *((int*)arg); while (1) { int amount rand() % 100; // 随机生成一个金额 pthread_mutex_lock(mutex); balance amount; // 增加余额 printf([生产者ID:%d] 存入 %d 元余额为 %d 元\n, id, amount, balance); pthread_cond_signal(cond); pthread_mutex_unlock(mutex); sleep(rand() % 3); // 随机休眠 } return NULL; } int main(int argc, const char *argv[]) { pthread_t ctid[NUM_CONSUMER]; pthread_t ptid[NUM_PRODUCER]; int cids[NUM_CONSUMER]; int pids[NUM_PRODUCER]; srand(time(NULL)); // 初始化随机数种子 for (int i 0; i NUM_CONSUMER; i) { cids[i] i 1; pthread_create(ctid[i], NULL, consumer, cids[i]); } for (int i 0; i NUM_PRODUCER; i) { pids[i] i 1; pthread_create(ptid[i], NULL, producer, pids[i]); } for (int i 0; i NUM_CONSUMER; i) { pthread_join(ctid[i], NULL); } for (int i 0; i NUM_PRODUCER; i) { pthread_join(ptid[i], NULL); } pthread_cond_destroy(cond); pthread_mutex_destroy(mutex); return 0; }条件变量的虚假唤醒只要用了条件变量做好while循环来判断