前面两篇给基本概念讲过了,大家有兴趣的可以去看一下:
Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地址空间,线程共享进程中的地址空间进程的创建消耗资源大,线程的创建相对较小进程的切换开销大,线程的切换开销相对较小进程:程序执行的过程叫进程。线程:进程内部的一条执行序列或执行路径,一个进程可以包含多条线程(多线程)!每个进程最少有一个线程,例如下面代码:#include <stdio.h>int main(){ return 0;} ...https://blog.csdn.net/qq_45829112/article/details/121458560Linux多线程的进阶理解_神厨小福贵!的博客-CSDN博客首先来看在Linux中如何实现多线程的,下面是《Linux内核设计与实现第三版》中扫描页的截图:这段话我冒昧的解析一下,如有不当,欢迎指出,大家共同进步!在Linux中线程和进程没有任何区别(站在内核角度来看),每个线程属于自己的task_struct,task_struct相当于在进程中的PCB(进程描述符),每创建一个新的进程就有一个新的进程描述符,在内核中线程看起来就是普通的进程,但是这个进程和它的主线程(在内核看来就是主进程)共享一块内存地址,同一个进程描述符!下面来看一段代码.https://blog.csdn.net/qq_45829112/article/details/121522914

下面来说一下Linux多线程中使用信号量和互斥锁对多线程进行同步!

先来看一下下面的一段代码来了解为什么需要对进程进行同步:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h> //多线程的创建  等待  退出所需的头文件int g_index = 1;void* fun(void* arg)
{for(int i = 0 ; i < 1000 ; i++){printf(" g_index = %d \n",g_index++);}
}int main()
{pthread_t id[5];for(int i = 0 ; i < 5 ; i++){pthread_create(&id[i],NULL,fun,NULL);}for(int i = 0 ; i < 5  ; i++){pthread_join(id[i],NULL);}exit(0);}

如上代码所示,该代码的初衷是想由主线程创建五个子线程来共同对全局变量g_index进行++的操作,理想中打印出来的结果应该是1 2 3  ......  5000

那么具体结果是如何呢,下面我们来看一下代码运行的结果:

这是第一次运行::

这是第二次运行:

 大家可以看看,仅仅是两次的运行,结果就大不相同,这只是两次的结果,如果多运行几次,那么结果可能千变万化。

我们先来说一下出现这种情况的原因是什么,请看下图:

那么如何解决这种情况呢,信号量和互斥锁

下面来看信号量:

先来看包含他们的头文件:#include <semaphore.h>

信号量的初始化int sem_init(sem_t *sem, int pshared, unsigned int value); 

第一个参数是信号量的地址;

第二个参数是释放需要两线程之间共享,这里我们用不到,给个0就好

第三个参数是信号量的初始值

信号量的p(对信号进行-1的操作)操作:int sem_wait(sem_t *sem);

信号量的v(对信号量进+1操作)操作:int sem_post(sem_t *sem); 

参数就是信号量的地址

信号量的销毁:int sem_destroy(sem_t *sem);

那么对于这道题来说,想要让五个子线程打印5000个有序的数来说,需要定义多少个信号量呢?大家好好想想,没思路的话,可以去看看这篇博客:Linux编程题:信号量同步三进程依次打印若干次ABC_神厨小福贵!的博客-CSDN博客

大家是不是以为定义5个信号量,来追着下一个信号量的尾巴,对它进行操作,然后打印吗?

错了(也不是完全错了),上面那种五个信号量适用于进程间的,而在线程中,他们是并发执行的,你要是搞5个信号量的,就是规定了每个线程的打印顺序,完全没必要,我们现在完全不关心谁先打印数字(谁先打印都无所谓的),我们关心的只是多个线程中同时只有一个能进行打印,所以一个信号量足够了,下面来看代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>  //信号量操作所需的头文件sem_t semid;    //定义信号量
int g_index = 1;void* fun(void* arg)
{for(int i = 0 ; i < 1000 ; i++){sem_wait(&semid);   //在g_index++之前进行减一操作,使得其他的线程堵塞printf(" g_index = %d \n",g_index++);sem_post(&semid);   //在g_index++之后进行加一操作,使得其他的线程得以正常运行}
}int main()
{sem_init(&sem,0,1);  //将信号量初始值给1pthread_t id[5];for(int i = 0 ; i < 5 ; i++){pthread_create(&id[i],NULL,fun,NULL);}for(int i = 0 ; i < 5  ; i++){pthread_join(id[i],NULL);}sem_destroy(&semid); //信号量的销毁函数exit(0);}

这样的话,我们来看一下运行结果!

这样的话,就让多线程并发执行进行同步!

下面再来看看互斥锁:

头文件就是线程创建函数的头文件:#include <pthread.h>

线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作, 其他线程才能操作,也就是协同步调,让线程按预定的先后次序进行运行。

互斥锁可以理解为就是在商场试衣间里面,你进去之后给试衣间上锁,然后其他人就必须等你解锁之后才可以正常使用这个试衣间,你在使用的时候,其他人只能阻塞(等你使用完)!

互斥锁的初始化:

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);

第一个参数是互斥锁的饿地址

第二个参数是互斥锁的属性,一般置为NULL

互斥锁的上锁:int pthread_mutex_lock(pthread_mutex_t *mutex);

互斥锁的解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex);

互斥锁的销毁:int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数都是互斥锁的地址

下面来看代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h> int g_index = 1;
pthread_mutex_t mutex;   //互斥锁的定义void* fun(void* arg)
{for(int i = 0 ; i < 1000 ; i++){pthread_mutex_lock(&mutex);    //互斥锁的上锁 printf(" g_index = %d \n",g_index++);pthread_mutex_unlock(&mutex);   //互斥锁的解锁}
}int main()
{pthread_mutex_init(&mutex,NULL);   //互斥锁的初始化pthread_t id[5];for(int i = 0 ; i < 5 ; i++){pthread_create(&id[i],NULL,fun,NULL);}for(int i = 0 ; i < 5  ; i++){pthread_join(id[i],NULL);}pthread_mutex_destroy(&mutex);exit(0);}

然后代码运行结果和上述的信号量一毛一样:

信号量和互斥锁的代码不难,难的是理解这种思想,因为这是线程,所以在定义信号量的时候,定义一个就够了,因为谁打印出那个数字,我不在乎,五个子线程谁抢到了谁就打印,但是每次只能有一个子线程在打印,互斥锁也是如此,每次只能一个线程去打印,理解了思想,这就可以了!

“累的时候,可以休息,但是弓出没有回头路,坚持走下去!”

Linux多线程的同步-----信号量和互斥锁相关推荐

  1. linux网络编程-posix信号量与互斥锁(39)

    -posix信号量信号量 是打开一个有名的信号量 sem_init是打开一个无名的信号量,无名信号量的销毁用sem_destroy sem_wait和sem_post是对信号量进行pv操作,既可以使用 ...

  2. Linux信号量与互斥锁解决生产者与消费者问题

    先来看什么是生产者消费者问题: 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问 ...

  3. Linux多线程的同步------读写锁

    前面介绍过Linux多线程同步的另外两个方法------互斥锁和信号量 Linux多线程的同步-----信号量和互斥锁_神厨小福贵!的博客-CSDN博客 下面来看一下读写锁: 读写锁和互斥锁都带有一个 ...

  4. Linux内核中的同步原语:自旋锁,信号量,互斥锁,读写信号量,顺序锁

    Linux内核中的同步原语 自旋锁,信号量,互斥锁,读写信号量,顺序锁 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Linux 内核中的同步原 ...

  5. linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题

    http://blog.csdn.net/jnu_simba/article/details/9123603 一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说 ...

  6. 漫画Linux 并发、竞态、互斥锁、自旋锁、信号量

    1. 锁的由来? 学习linux的时候,肯定会遇到各种和锁相关的知识,有时候自己学好了一点,感觉半桶水的自己已经可以华山论剑了,又突然冒出一个新的知识点,我看到新知识点的时候,有时间也是一脸的懵逼,在 ...

  7. 信号量,互斥锁,条件变量的联系与区别

    转自:http://blog.chinaunix.net/u3/108685/showart_2127853.html 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程, ...

  8. 210224阶段三信号量、互斥锁

    目录 一.学习的知识点 进程 线程 进程和线程 信号量和互斥锁 应用场景 二.上课没有听懂或者没有理解的地方 三.当天学习的收获 一.学习的知识点 ls -a 显示隐藏文件 cd ~ 回到home目录 ...

  9. 信号量和互斥锁的区别

    一:信号量与互斥锁之间的区别: 互斥量用于线程的互斥,信号线用于线程的同步.这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别. 互斥量值只能为0/1,信号量值可以为非负整数. 也就是说,一个互 ...

最新文章

  1. 与人相处时不越界,能让关系更和谐
  2. 沉痛悼念 pip search 一路走好
  3. 学习dos批处理,再也不怕老板安排一些重复性高的工作了,几行代码就搞定!
  4. 理解Bias(偏差),Error(误差),和Variance(方差)的区别和联系?
  5. 计算机与人脑_要把人脑连到计算机上!马斯克真敢想,但人类准备好了吗?
  6. C++ 基于 Visual C++6.0 的 DLL 编程实现
  7. 使用“微服务+云架构”轻松应对系统扩容!
  8. java后端路由中转
  9. 汇编语言 王爽 【第四版】 第一章 检测点1.1
  10. win2008php一键,WIN2008 一键安装PHP环境PHP5.3+FastCGI
  11. python中文分词的主要方法
  12. 串行加法器和并行加法器_N位并行加法器(4位二进制加法器和减法器)
  13. linux 修改网卡 mac地址命令,Centos系统下查看和修改网卡Mac地址(附ifconfig命令格式)...
  14. 银联在线java接口开发_银联在线Java接口开发
  15. 高斯帕滑翔机枪matlab,高斯帕滑翔机枪的播种机这么做?
  16. 优秀的 Node.js 包汇总
  17. 请记住这个数字-2147483648到2147483647
  18. python画饼状图
  19. 机器学习方向博士毕业有5篇三大会(ICML、Neurips、ICLR)是什么水平?
  20. 人工智能-作业6:CNN实现XO识别

热门文章

  1. TSR交通标志检测与识别
  2. 常用数据结构讲解与案例分析
  3. [JavaScript] 函数作用域问题
  4. [JAVAEE] 使用Postman测试接口
  5. HarmonyOS 实现跑马灯效果
  6. 微信小程序 文字换行
  7. Volley 请求提示:com.android.volley.ClientError
  8. java 增强for循环(foreach)
  9. Plugin Error
  10. mysql的时间存储格式