资讯专栏INFORMATION COLUMN

我的物联网之路—Linux中的C编程—多线程编程

番茄西红柿 / 2839人阅读

摘要:互斥锁使得共享资源按序在各个线程中操作。可分为快速锁递归互斥锁检错互斥锁信号量信号量也是操作系统中所用到的原语它广泛用于进程或线程间的同步与互斥本质上是非负的整数计数器当信号量的值大于或等于时该线程具有公共资源的访问权限。

日期变更记录
2021-9-29创建

什么是线程

线程是在共享内存空间种并发的多道执行路径,它们共享一个进程的资源。进程是系统中程序执行和资源分配的基本单位。线程是进程内的基本调度单位,也可以称为轻量级进程

线程分类

1. 用户级线程

2. 核心级线程

线程基本操作

由于线程共享进程的资源和地址空间,因此在对这些资源进行操作时,必须考虑到线程间资源访问的唯一性问题,这里介绍的是POSIX中线程同步的方法,主要有互斥锁和信号量的方式

互斥锁

互斥锁只有两种状态,就是上锁和解锁。互斥锁使得共享资源按序在各个线程中操作。可分为:快速锁、递归互斥锁、检错互斥锁

信号量

信号量也是操作系统中所用到的PV原语,它广泛用于进程或线程间的同步与互斥,本质上是非负的整数计数器,当信号量sem的值大于或等于0时,该线程具有公共资源的访问权限。互斥与同步的区别在于,互斥用的是同一个信号量,同步反之。

Example

线程创建

#include #include #include void *pthread_2(void *param){    int i;    // pthread_cancel(*(pthread_t *)param);    // 取消th1线程,那么就不会去执行pthread_1函数了    for (i = 0; i < 10; i++)    {         printf("我是线程2:%d/n", i);         sleep(1);         if(i == 5)         {            pthread_exit("exit");         }    }}void *pthread_1(void *param){    pthread_cancel(*(pthread_t *)param);    // 根据创建线程的函数,会先执行pthread_2一次然后回到pthread_1函数    // 但是又把th2传过来,把th2线程取消掉    while (1)    {        printf("我是线程1/n");        sleep(1);    }    }int main(int argc, char *argv[]){    pthread_t th1,th2;    printf("主进程,下面开始创建线程/n");    pthread_create(&th1, NULL, pthread_1, (void *)&th2);    // 创建线程标识符为th1,pthread_1是线程起始地址    pthread_create(&th2, NULL, pthread_2, (void *)&th1);    // 创建线程标识符为th2,pthread_2是线程起始地址,把th1传到pthread_2中    printf("线程创建结束/n");    pthread_join(th1, NULL);    // 将线程挂起,等待结束    pthread_join(th2, NULL);}

互斥锁

#include #include #include pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁// 创建快速互斥锁int flag = 0;void *pthread_2(void *param){    int i;    pthread_mutex_lock(&mutex);    // 锁住线程资源    for (i = 0; i < 10; i++)    {         printf("我是线程2:%d/n", i);         sleep(1);    }    pthread_mutex_unlock(&mutex);    // 解锁}void *pthread_1(void *param){    int i;    pthread_mutex_lock(&mutex);    for (i = 0; i < 10; i++)    {         printf("我是线程1:%d/n", i);         sleep(1);    }    pthread_mutex_unlock(&mutex);}int main(int argc, char *argv[]){    pthread_t th1,th2;    //pthread_mutex_init(&mutex, PTHREAD_MUTEX_INITIALIZER);    printf("主进程,下面开始创建线程/n");    pthread_create(&th1, NULL, pthread_1, NULL);    pthread_create(&th2, NULL, pthread_2, (void *)&th1);    // 会先去执行th1的线程    printf("线程创建结束/n");    pthread_join(th1, NULL);    // 将线程吊起    pthread_join(th2, NULL);}

信号量

信号量互斥

#include #include #include #include sem_t sem;//sem信号量实现三个线程互斥void *pthread_3(void *param){    int i;    sem_wait(&sem); //sem = sem -1;      for (i = 0; i < 10; i++)    {         printf("我是线程3:%d/n", i);         sleep(1);    }    sem_post(&sem);  //sem = sem + 1; }void *pthread_2(void *param){    int i;    sem_wait(&sem); //sem = sem -1;      for (i = 0; i < 10; i++)    {         printf("我是线程2:%d/n", i);         sleep(1);    }    sem_post(&sem);  //sem = sem + 1; }void *pthread_1(void *param){    int i;    sem_wait(&sem);  //sem = sem -1;      for (i = 0; i < 10; i++)    {         printf("我是线程1:%d/n", i);         sleep(1);    }    sem_post(&sem);  //sem = sem + 1; }int main(int argc, char *argv[]){    pthread_t th1,th2, th3;    sem_init(&sem, 0, 1);    // 信号量初始化1    printf("主进程,下面开始创建线程/n");    pthread_create(&th1, NULL, pthread_1, NULL);    pthread_create(&th2, NULL, pthread_2, NULL);    // 首先去执行th1线程    pthread_create(&th3, NULL, pthread_3, NULL);    printf("线程创建结束/n");    pthread_join(th1, NULL);    // 将线程掉起    pthread_join(th2, NULL);    pthread_join(th3, NULL);}

信号量同步

#include #include #include #include sem_t sem1, sem2, sem3;//3个线程1,2,3//执行顺序 3 1 2void *pthread_3(void *param){    int i;    sem_wait(&sem1); //sem = sem -1;    for (i = 0; i < 10; i++)    {        printf("我是线程3:%d/n", i);        sleep(1);    }    sem_post(&sem3); //sem = sem + 1;}void *pthread_2(void *param){    int i;    sem_wait(&sem2); //sem = sem -1;    for (i = 0; i < 10; i++)    {        printf("我是线程2:%d/n", i);        sleep(1);    }    sem_post(&sem1); //sem = sem + 1;}void *pthread_1(void *param){    int i;    sem_wait(&sem3); //sem = sem -1;    for (i = 0; i < 10; i++)    {        printf("我是线程1:%d/n", i);        sleep(1);    }    sem_post(&sem2); //sem = sem + 1;}int main(int argc, char *argv[]){    pthread_t th1, th2, th3;    sem_init(&sem1, 0, 1);    sem_init(&sem2, 0, 0);    sem_init(&sem3, 0, 0);    printf("主进程,下面开始创建线程/n");    pthread_create(&th1, NULL, pthread_1, NULL);    pthread_create(&th2, NULL, pthread_2, NULL);    pthread_create(&th3, NULL, pthread_3, NULL);    // 初始化后,sem1 = 0 ,sem2 ,sem3 =-1    printf("线程创建结束/n");    pthread_join(th1, NULL);    pthread_join(th2, NULL);    pthread_join(th3, NULL);}

函数说明

pthread_create

pthread_exit

pthread_join

pthread_mutex_init

pthread_mutex_lock

pthread_mutex_trylock

pthread_mutex_unlock

pthread_mutex_destroy

sem_init

sem_wait

sem_trywait

sem_post

sem_getvalue

sem_destroy

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121629.html

相关文章

  • 从小白程序员一路晋升为大厂高级技术专家我看过哪些书籍?(建议收藏)

    摘要:大家好,我是冰河有句话叫做投资啥都不如投资自己的回报率高。马上就十一国庆假期了,给小伙伴们分享下,从小白程序员到大厂高级技术专家我看过哪些技术类书籍。 大家好,我是...

    sf_wangchong 评论0 收藏0
  • 我的编程之路:勤能补拙

    摘要:简单介绍一下自己和目前的工作我是一名驱动工程师,目前就职于杭州通信公司,从事手机底层驱动的调试与编写工作。读研究生期间,由于各项研究都离不开编程,所以只能硬着头皮逼自己去学习。身为汉子,至今单身。 简单介绍一下自己和目前的工作我是一名Linux驱动工程师,目前就职于杭州*通信公司,从事手机底层驱动的调试与编写工作。详细写写你是如何走上编程的道路研究生之前比较喜欢玩,所以那是压根就没有想...

    netmou 评论0 收藏0
  • 我的编程之路:勤能补拙

    摘要:简单介绍一下自己和目前的工作我是一名驱动工程师,目前就职于杭州通信公司,从事手机底层驱动的调试与编写工作。读研究生期间,由于各项研究都离不开编程,所以只能硬着头皮逼自己去学习。身为汉子,至今单身。 简单介绍一下自己和目前的工作我是一名Linux驱动工程师,目前就职于杭州*通信公司,从事手机底层驱动的调试与编写工作。详细写写你是如何走上编程的道路研究生之前比较喜欢玩,所以那是压根就没有想...

    MSchumi 评论0 收藏0
  • 面试:Semaphore(信号量)的成长之路

    摘要:最寒冷,面试跳槽不能等马上就月份了,所谓的金三银四招聘季。在中有两种模式,分别是线程池和信号量,说到这里大家明白了吧,信号量的作用。感兴趣的同学可以去了解下,讲了线程,线程池,锁,,等内容。 2019最寒冷,面试跳槽不能等 马上就3月份了,所谓的金三银四招聘季。2019年也许是互联网最冷清的一年,很多知名的大型互联网公司都裁员过冬。当然也有一些公司还在持续招人的,比如阿里就宣称不裁员,...

    Lorry_Lu 评论0 收藏0
  • JavaScript在物联网中的应用

    摘要:定律在那篇最流行的编程语言能做什么里,我们列举了在不同领域的使用情况,今天让我们来详解一下在物联网中的应用。这个硬件层决定了物联网应用比应用更加复杂。这时,我开始关注实现物联网应用的可能性。 凡是能用JavaScript写出来的,最终都会用JavaScript写出来。 —— Atwood定律 在那篇《最流行的编程语言JavaScript能做什么?》里,我们列举了JavaScript在不...

    aaron 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<