本文共 2995 字,大约阅读时间需要 9 分钟。
0x00 前言
由于最近在开发一个工具时需要使用 Perl 的多线程功能,我联想到 POSIX C 中关于条件变量的实现。为了验证自己的猜想是否正确,我做了一个实验,成功实现了对 POSIX PTHREAD 的一部分猜想的证实。0x01 理论分析
在 Linux 系统中,进程和子进程共享父进程的资源,但每个进程都有自己的堆栈空间。虽然子进程在创建时只是拷贝了父进程的 PID 和一些基本信息,但在后续操作中需要复制资源。与之相反,线程只占用生成线程进程的一部分栈空间,因此线程不会有自己的资源。竞争的前提是资源共享。解决竞争的核心是对共享资源进行划分或将其限制为临界区,以实现 CPU 处理的时分空间并行。
互斥锁机制是针对单一资源共享形成临界区的解决方案。等待锁的线程会消耗 CPU 时间,但互斥锁嵌套可以避免死锁。通过按操作顺序加锁,可以对多个共享资源进行管理。
条件变量结合互斥锁是解决多资源共享且操作有序性的高效方式。在进入条件变量的临界区后,如果条件不满足,线程会解锁并让出 CPU,等待条件满足后再通过信号通知等待线程继续处理。
信号量是解决多资源并行处理临界区的另一种方式,强调资源的并行性和有无,即 P、V 操作。
0x02 实践分析
#include#include #include #define FOR_END 10int index;pthread_mutex_t mutex;pthread_cond_t cond_t;void *thread_func_one(void *args) { for (index = 0; index < FOR_END; index++) { pthread_mutex_lock(&mutex); if (!(index % 2)) { printf("pthread one signal before\n"); pthread_cond_signal(&cond_t); printf("pthread one signal\n"); } printf("pthread one print %d\n", index); pthread_mutex_unlock(&mutex); sleep(1); } pthread_cond_signal(&cond_t); index = -1;}void *thread_func_two(void *args) { while (1) { pthread_mutex_lock(&mutex); if (index == -1) { break; } if (index % 2) { printf("pthread two wait before\n"); pthread_cond_wait(&cond_t, &mutex); printf("pthread two wait\n"); } printf("pthread two print %d\n", index); pthread_mutex_unlock(&mutex); sleep(1); }}int main(int argc, char *argv[]) { pthread_t pt_one, pt_two; int pid_one, pid_two; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond_t, NULL); pid_one = pthread_create(&pt_one, NULL, thread_func_one, NULL); if (pid_one) { printf("thread one create failed!\n"); return -1; } pid_two = pthread_create(&pt_two, NULL, thread_func_two, NULL); if (pid_two) { printf("thread two create failed!\n"); return -1; } pthread_join(pt_one, NULL); pthread_join(pt_two, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond_t); return 0;}
程序输出结果:
pthread one signal beforepthread one signalpthread one print 0pthread two print 0pthread one print 1pthread two wait beforepthread one signal beforepthread one signalpthread one print 2pthread two waitpthread two print 2pthread one print 3pthread two wait beforepthread one signal beforepthread one signalpthread one print 4pthread two waitpthread two print 4pthread one print 5pthread two wait beforepthread one signal beforepthread one signalpthread one print 6pthread two waitpthread two print 6pthread one print 7pthread two wait beforepthread one signal beforepthread one signalpthread one print 8pthread two waitpthread two print 8pthread one print 9pthread two wait beforepthread two waitpthread two print -1
0x03 结尾
以上程序展示了以下内容:a. pthread_cond_wait: 该函数会阻塞当前线程,释放锁并释放 CPU 时间片,等待信号后再获取 CPU 时间片继续执行。b. pthread_cond_signal: 每次只能唤醒一个正在等待的线程。转载地址:http://jjxfk.baihongyu.com/