七、Linux应用编程和网络编程之线程

    xiaoxiao2025-06-04  31

    目录

    1、进程和线程

    2、线程

    3、线程同步之信号量

    4、线程同步之互斥锁

    5、线程同步之条件变量


    1、进程和线程

    1.1、使用进程技术的优势和劣势

    优势:

    CPU时分复用,单核心CPU可以实现宏观上的并行实现多任务系统需求(多任务的需求是客观的)

    劣势:

    进程间切换开销大进程间通信麻烦而且效率低

    进程与进程之间天生是隔离的,好处是安全,坏处是进程间通信很麻烦

    1.2、线程技术

    (1)线程技术保留了进程技术实现多任务的特性。

    (2)线程的改进就是在线程间切换和线程间通信上提升了效率。

    (3)多线程在多核心CPU上面更有优势。

     

    2、线程

    (1)一种轻量级进程

    (2)线程是参与内核调度的最小单元

    (3)一个进程中可以有多个线程

    2.1线程技术的优势

    (1)像进程一样可被OS调度

    (2)同一进程的多个线程之间很容易高效率通信

    (3)在多核心CPU(对称多处理器架构SMP)架构下效率最大化

    多核CPU不能保证多个进程在多个CPU核心上同时运行,但多线程可以保证在多个核心上调度

    2.2、线程常见函数

    (1)线程创建与回收:

    pthread_create 主线程用来创造子线程的pthread_join 主线程用来等待(阻塞)回收子线程pthread_detach 主线程用来分离子线程,分离后主线程不必再去回收子线程

    (2)线程取消:

    pthread_cancel 一般都是主线程调用该函数去取消(让它赶紧死)子线程pthread_setcancelstate 子线程设置自己是否允许被取消pthread_setcanceltype

    (3)线程函数退出相关:

    pthread_exit与return退出pthread_cleanup_pushpthread_cleanup_pop

    (4)获取线程id:

    pthread_self

     

    3、线程同步之信号量

    任务:用户从终端输入任意字符然后统计个数显示,输入end则结束

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <pthread.h> #include <stdlib.h> #include <semaphore.h> char buf[200]; sem_t sem; unsigned int flag = 0; void *func(void *arg); int main(void) { pthread_t th = -1; int ret = -1; sem_init(&sem, 0, 0); // 创建一个子线程 ret = pthread_create(&th, NULL, func, NULL); if (ret != 0) { printf("error\n"); exit(-1); } printf("请输入一个字符串,以回车结尾:\n"); while (scanf("%s", buf)) { if (!strcmp("end", buf)) { printf("退出\n"); flag = 1; sem_post(&sem); break; } //主线程在收到用户输入的字符串,并且确认不是end后,就去发信号激活子线程来计数。 sem_post(&sem); } // 回收子进程 ret = pthread_join(th, NULL); if (ret != 0) { printf("pthread_join error.\n"); exit(-1); } printf("子线程回收成功\n"); sem_destroy(&sem); return 0; } // 子线程 void *func(void *arg) { // 被唤醒,没有收到激活信息时会一直阻塞在这里 sem_wait(&sem); // 子线程需要有一个循环,否则打印一次就退出了 while (flag == 0) { printf("%d个字符\n", strlen(buf)); memset(buf, 0, sizeof(buf)); sem_wait(&sem); // 每打印一次都要阻塞,等待下一次激活 } }

    4、线程同步之互斥锁

    (1)什么是互斥锁

    互斥锁又叫互斥量(mutex)相关函数:pthread_mutex_init pthread_mutex_destroy pthread_mutex_lock pthread_mutex_unlock

    (2)互斥锁和信号量的关系:可以认为互斥锁是一种特殊的信号量

    (3)互斥锁主要用来实现关键段代码保护

    (4)互斥锁可以实现上节代码的功能,通过上锁和解锁以及sleep()实现,但并非互斥锁的标准用法,代码效率很低

     

    5、线程同步之条件变量

    相关函数

    pthread_cond_init pthread_cond_destroy

    pthread_cond_wait pthread_cond_signal/pthread_cond_broadcast

    代码实践(条件变量和互斥锁需要共同使用,子线程里的互斥锁也是有意义的)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdlib.h> char buf[200]; pthread_mutex_t mutex; pthread_cond_t cond; unsigned int flag = 0; void *func(void *arg); int main(void) { pthread_t th = -1; int ret = -1; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); // 创建一个子线程 ret = pthread_create(&th, NULL, func, NULL); if (ret != 0) { printf("error\n"); exit(-1); } printf("请输入一个字符串,以回车结尾:\n"); while (1) { scanf("%s", buf); // 阻塞 pthread_cond_signal(&cond); // 条件满足会发送信号,pthread_cond_wait()不再阻塞 if (!strcmp("end", buf)) { printf("退出\n"); flag = 1; break; } } // 回收子进程 ret = pthread_join(th, NULL); if (ret != 0) { printf("pthread_join error.\n"); exit(-1); } printf("子线程回收成功\n"); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0; } // 子线程 void *func(void *arg) { // 子线程需要有一个循环,否则打印一次就退出了 while (flag == 0) { pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); printf("%d个字符\n", strlen(buf)); memset(buf, 0, sizeof(buf)); pthread_mutex_unlock(&mutex); } }

     

    文章参考朱友鹏老师物联网课程整理

    最新回复(0)