Linux从入门到开发实战(C/C++)Day10-线程

news/2024/11/9 16:46:12/

1.概念:
        线程是一个函数,是os调度的基本单位
        Linux内核在2.2版本之前,是没有线程的概念,只有有限个进程(4096)
                在2.4版本中,有了线程的概念,而且可以有无数个
        主线程一般默认main函数
        分支线程一般是被创建的线程
        一个进程中至少有一个线程,同一进程中的线程共享进程的所有资源(全局变量)
        多个线程可以用一个线程函数,函数中的局部变量是每个线程独有的(不共用)

    2.如何创建并启用线程
        #include <pthread.h>

        pthread_create    创建线程(man pthread_create)
        int pthread_create(
                            pthread_t *thread,                         //线程id,作为返回参数
                            const pthread_attr_t *attr,              //线程属性
                              void *(*start_routine) (void *),      //线程函数
                            void *arg                                        //线程函数参数
                            );
         Compile and link with -pthread.    
         //程序中使用了这个函数,生成时要链接库 gcc *.c -l pthread 

         线程传参
             参数为void* 注意类型转换即可

        线程结束:
            自然结束
                线程函数结束
            主线程结束
                主线程结束时会结束掉分支线程
            用pthread_exit
                与exit函数类似
             其他线程发送信号给线程
                 pthread_kill

             其他线程结束线程
                 pthread_cancel

             获取线程返回值
                 pthread_join 阻塞函数,直到获取的线程结束,这个函数才返回,一般是用它等待某线程结束
    
    3.临界数据
        多个线程同时运行,都可以访问到的数据叫做临界数据
        多个线程同时访问临界数据后,导致临界数据脏(结果不对)

    4.线程同步
        通过各种方式让并发执行的线程不同时访问同一块区域
            原子锁    atomic_add(老版本的有,现在不支持了)特性:不可分割

            自旋锁    pthread_spinlock_init
                一直在循环等待
                互斥锁建立锁消耗多,当线程阻塞的时候不会一直循环,处于阻塞情况下不消耗资源
                自旋锁建立锁消耗资源少,当线程阻塞的时候一直循环检查锁是否可用,处于阻塞情况下消耗资源
                互斥锁适用于阻塞时间长的情况
                自旋锁适用于阻塞时间短的情况
                pthread_spinlock_t
                pthread_spinlock_init
                pthread_spinlock_lock
                pthread_spinlock_unlock
                pthread_spinlock_destory
                也可以和条件变量联用让线程相对均匀分配
            信号量(旗语)

            读写锁    pthread_rwlock_init
                有两把锁,一把 读 锁,一把 写 锁,读写、写写相斥,读读相容
                pthread_rwlock_t        创建
                pthread_rwlock_init        初始化
                pthread_rwlock_wrlock    加写锁
                pthread_rwlock_rdlock    加读锁
                pthread_rwlock_unlock    解锁
                pthread_rwlock_destory    销毁


            互斥量    pthread_mutex_init
                相互排斥,某个线程加了锁,其他线程在解锁前都阻塞
                可能某个线程很久都抢不到加锁权(不能均匀分配cpu时间片)
                如果希望多个线程相对公平,就要和条件变量一起使用

            条件变量    pthread_cond_init
                pthread_cond_t             创建
                pthread_cond_init         初始化
                pthread_cond_wait         等待信号(阻塞式)
                pthread_cond_signal     向某个线程发送信号
                pthread_cond_bordcast     向所有线程发送信号
                pthread_cond_destroy     销毁信号

        通用编程模型:
            1.创建锁/变量
            2.初始化
            3.使用
                加锁
                解锁
            4.销毁锁
        死锁:线程卡死
            死锁产生必须要满足的四点:
                1)请求且保持
                2)不可撤销
                3)不可摧毁
                4)循环请求
        粒度:一把锁锁住的范围
            粒度小 锁越多 越灵活 消耗的资源越多
            粒度大 锁越少 越不灵活 消耗的资源越少

// pthread
void *func(void *arg)
{int n = 0;while (1){printf("分支线程:%d\n", n--);sleep(2);}
}
void _pthread()
{int n = 0;pthread_t pt = 0;printf("pt: %u\n", pt);pthread_create(&pt, NULL, func, NULL);while (1){printf("主线程:%d\n", n++);sleep(2);}
}// 1.创建互斥量
pthread_mutex_t mutex;
int num = 0;
void f_mutex()
{for (size_t i = 0; i < 1000; i++){// 3.使用互斥量前加锁pthread_mutex_lock(&mutex);num++;// 用完解锁pthread_mutex_unlock(&mutex);}
}
void _pthread_mutex()
{pthread_t t1, t2;/// 2.初始化互斥量pthread_mutex_init(&mutex, NULL);pthread_create(&t1, NULL, f_mutex, NULL);pthread_create(&t2, NULL, f_mutex, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);printf("%d\n", num);// 4.销毁互斥量pthread_mutex_destroy(&mutex);
}
//
// 互斥量与条件变量一起用
pthread_mutex_t mutex_1;
pthread_cond_t cond_1;
void f1()
{while (1){pthread_mutex_lock(&mutex_1);pthread_cond_wait(&cond_1, &mutex_1);printf("===线程1===\n");sleep(1);pthread_mutex_unlock(&mutex_1);}
}
void f2()
{while (1){pthread_mutex_lock(&mutex_1);pthread_cond_wait(&cond_1, &mutex_1);printf("---线程2---\n");sleep(1);pthread_mutex_unlock(&mutex_1);}
}
void f3()
{while (1){pthread_mutex_lock(&mutex_1);pthread_cond_wait(&cond_1, &mutex_1);printf("+++线程3+++\n");sleep(1);pthread_mutex_unlock(&mutex_1);}
}
void _pthread_mutexAndCond()
{pthread_t t1, t2, t3;/// 2.初始化pthread_mutex_init(&mutex_1, NULL);pthread_cond_init(&cond_1, NULL);pthread_create(&t1, NULL, f1, NULL);pthread_create(&t2, NULL, f2, NULL);pthread_create(&t3, NULL, f3, NULL);while (1){pthread_cond_signal(&cond_1);sleep(1);}pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);// 4.销毁pthread_mutex_destroy(&mutex_1);pthread_cond_destroy(&cond_1);
}


http://www.ppmy.cn/news/1524936.html

相关文章

安全工具 | 使用Burp Suite的10个小tips

Burp Suite 应用程序中有用功能的集合 img Burp Suite 是一款出色的分析工具&#xff0c;用于测试 Web 应用程序和系统的安全漏洞。它有很多很棒的功能可以在渗透测试中使用。您使用它的次数越多&#xff0c;您就越发现它的便利功能。 本文内容是我在测试期间学到并经常的主要…

配环境时的一些记录

连centos&#xff1a;正常连就好&#xff08;密码验证码&#xff09;连rocky&#xff1a;需要在centos上连&#xff0c;终端里直接ssh [rocky_ip]&#xff1b;在vscode中需要&#xff1a; 修改配置文件&#xff1a;打开命令面板&#xff08;ctrlshiftp&#xff09; -> 输入并…

Android命令行查看CPU频率和温度

在 Android 设备上&#xff0c;你可以通过命令行工具 adb 来查看 CPU 温度和 CPU 频率&#xff0c;并确定是否有降频情况。以下是具体步骤&#xff1a; 1. 查看 CPU 频率 你可以使用以下命令来查看 CPU 各个核心的当前频率&#xff1a; adb shell cat /sys/devices/system/c…

基于Spring Boot的旧物置换网站

构建一个基于Spring Boot的旧物置换网站是一个很好的项目&#xff0c;可以帮助你学习如何设计和实现一个完整的Web应用程序。以下是一个简化版的示例&#xff0c;展示了如何搭建这样一个系统的框架。 1. 创建Spring Boot项目 首先&#xff0c;你需要创建一个新的Spring Boot项…

VUE,element-ui,优化tabs组件每次点击,所有子页面都重新渲染问题

1.在data中定义每个子组件相应的值&#xff0c;ture为加载&#xff0c;false为不加载。 2.在子组件中使用v-if来判断是否渲染当前页面 3.在函数中对子组件的值进行切换。 handleClick(){if(this.activeNamefirst){this.pageOne truethis.pageTwo false}else if(this.active…

如何识别和防范跨站请求伪造(CSRF)?

识别和防范跨站请求伪造&#xff08;CSRF&#xff09;的关键在于理解其攻击原理并采取相应的措施。以下是一些识别和防范CSRF的方法&#xff1a; 识别CSRF的方法&#xff1a; 异常请求&#xff1a;留意网站中是否有意外的GET或POST请求&#xff0c;尤其是那些涉及到敏感操作&a…

PostgreSQL-05-入门篇-数据分组

文章目录 1. GROUP BY 分组简介示例1) 不使用聚合函数的 GROUP BY2) 使用 SUM() 函数的 GROUP BY3) 结合 JOIN 子句的 GROUP BY4) 使用 COUNT() 函数的 GROUP BY5) 多列 GROUP BY6) 使用日期列的 GROUP BY 2. HAVING 子句简介HAVING 对比 WHEREPostgreSQL HAVING 子句示例1) 使…

【Java-简单练习题】

1.”AABBBCCC“>>"A2B3C3" public class Test6 {public static void main(String[] args) {String ns "AABBBCCCC";String retcompress(ns);System.out.println(ret);}public static String compress(String str) {StringBuilder ret new StringB…