Linux下的多线程编程:原理、工具及应用(2)

这篇具有很好参考价值的文章主要介绍了Linux下的多线程编程:原理、工具及应用(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux下的多线程编程:原理、工具及应用(2),Linux练功 初阶功法,linux,运维,服务器,大数据

                                               🎬慕斯主页修仙—别有洞天

                                              ♈️今日夜电波:Flower of Life—陽花

                                                                0:34━━━━━━️💟──────── 4:46
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

理解互斥锁

前置知识

通过伪代码进行理解

死锁

线程同步的概念

生产者消费者模型

概述

如何理解CP问题?

再次理解条件变量


理解互斥锁

        通过上一篇对于互斥锁操作的基本理解,现在我们从底层理解一下互斥锁的原理:

前置知识

        1、为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性
        2、从上面对于锁的理解,我们可以知道,锁其实是一个自定义的结构体类型。现在我们可以先这样简单的理解一下这个结构体类型,真正的结构体类型肯定是包涵很多安全属性之类的:

struct 
{
  int mutex=1;
}

        3、寄存器硬件在CPU内部只有一套,但是寄存器的内容每一个线程都有一份,拥有属于自己的上下文!

通过伪代码进行理解

        知道了上面的前置知识后,我们通过以下的伪代码真正的理解:

Linux下的多线程编程:原理、工具及应用(2),Linux练功 初阶功法,linux,运维,服务器,大数据

lock:

        注意上面的汇编语句都是原子性的!可以看到第一段movb $0,%a1表示为将数值0移动到寄存器 %a1 的最低字节,就是初始化%a1为0.然后通过xchgb %a1,mutex交换寄存器和内存单元中的数据。由于我们的锁的定义实际上就是一个自定义类型的定义,因此,他当然是存储在内存中的啦!我们可以通过以下图示来理解:

Linux下的多线程编程:原理、工具及应用(2),Linux练功 初阶功法,linux,运维,服务器,大数据

        接着继续理解,下面是一段if判断的伪代码,判断al寄存器中的内容是否大于0,如果我们的线程还在时间片内,那么他就是大于0的会返回0,当时间片用完,那么我们的其他寄存器等会保存上下文。新的进程进来了,同样有锁,需要初始化al为0,然后交换内存中的数据,但是!重要的来了,此时内存中的mutex是0!我们换后还是0!,此时进行if判断,就会挂起等待!!!这就是加锁的底层原理!

unlock:

        解锁可以看到movb $1,%a1就是初始化%a1为1,然后唤醒被因Mutex挂起等待的线程即可。

死锁

        死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

###死锁四个必要条件

互斥条件:一个资源每次只能被一个执行流使用

请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放

不剥夺条件:一个执行流已获得的资源,在末使用完之前,不能强行剥夺

循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系

###避免死锁

破坏死锁的四个必要条件

加锁顺序一致

避免锁未释放的场景

资源一次性分配

线程同步的概念

###条件变量

当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。

例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量。


####同步概念与竞态条件

同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步。

竞态条件:因为时序问题,而导致程序异常,我们称之为竞态条件。在线程场景下,这种问题也不难理解

生产者消费者模型

概述

        生产者消费者模型,我们可以这样理解:有一间商店,消费者要去买东西,生产者要供货。而在这之间我们可以将生产者与消费者分别理解为线程,而商店理解为内存空间(基于特定空间的数据结构或者容器),而这个商店是用于进行执行流间数据的传递的!可以理解为临界资源!在这个模型中,我们需要保证生产消费的过程是安全的!因此我们需要遵守以下的原则:可以简称为“321原则”。

1、3种关系:(本质就是用锁&&条件变量维护)

生产者与生产者之间是什么关系?竞争—互斥

消费者与消费者之间是什么关系?竞争—互斥

生产者与消费者之间是什么关系?互斥&&同步

2、2种角色

生产者(1 or n)、消费者(1 or n) --线程或者进程

3、1个交易场所

内存空间

如何理解CP问题?

        在生产者消费者模型中,CP问题通常指的是生产者和消费者之间的同步问题,即如何保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区空时取出数据。这个问题可以通过使用多线程编程中的同步机制来解决。具体来说,有以下几个方面:

  1. 共享缓冲区:生产者和消费者共享一个固定大小的缓冲区,生产者向其中放入数据,消费者从其中取出数据。
  2. 同步机制:为了避免生产者在缓冲区满时继续生产数据,以及消费者在缓冲区空时继续消费数据,需要使用同步机制。常见的同步机制包括互斥锁(mutex)和条件变量(condition variable)。互斥锁用于保护共享资源,防止同时读写;条件变量则用于实现线程间的等待和通知机制。
  3. 状态一致性:需要确保在任何时刻,缓冲区的数据状态都是一致的。这意味着在消费者取出数据后,必须及时更新缓冲区的状态,以防止其他消费者错误地认为还有数据可取。
  4. 生产者限制:生产者在生产数据时,需要检查缓冲区是否已满。如果缓冲区已满,生产者必须等待,直到消费者取出数据并通知生产者可以继续生产。
  5. 消费者限制:消费者在消费数据时,需要检查缓冲区是否为空。如果缓冲区为空,消费者必须等待,直到生产者放入数据并通知消费者可以继续消费。
  6. 编码实践:在实现生产者-消费者模型时,需要注意避免竞态条件和死锁。正确的使用同步机制是解决这些问题的关键。
  7. 实际应用:生产者-消费者模型在分布式系统、并发编程和实时系统中非常常见,它是理解和解决并发问题的基础模型之一。

再次理解条件变量

        生产者消费者模型会有数据不一致的问题,上面提到为了满足线程同步,光加锁是不够的,可能会有饥饿的问题。因此,我们需要定义“条件变量”来让线程不做无效的锁申请,执行具有顺序。我们可以先简单的用以下的结构体先理解条件变量:

struct cond
{
  //条件是否就绪
  int flag;
  //维护一个线程队列
  tcb_queue;
}

                      感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       Linux下的多线程编程:原理、工具及应用(2),Linux练功 初阶功法,linux,运维,服务器,大数据

                                                                        给个三连再走嘛~  文章来源地址https://www.toymoban.com/news/detail-841046.html

到了这里,关于Linux下的多线程编程:原理、工具及应用(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt的多线程编程

    并发 当有多个线程在操作时,如果系统 只有一个CPU ,则它根本不可能真正同时进行一个以上的线程,它只能把 CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其他线程处于挂起状态。 虽然看起来所有 线程都是一起执行

    2024年02月08日
    浏览(42)
  • “深入理解Java的多线程编程“

    多线程编程是指在一个程序中同时运行多个线程,以提高程序的并发性和性能。Java是一门支持多线程编程的强大编程语言,提供了丰富的多线程相关类和接口。 在Java中,可以通过以下方式实现多线程编程: 继承Thread类:创建一个继承自Thread类的子类,并重写run()方法,在

    2024年02月13日
    浏览(63)
  • C# 中的多线程和异步编程

    最近在看代码的过程中,发现有很多地方涉及到多线程、异步编程,这是比较重要且常用的知识点,而本人在这方面还理解尚浅,因此开始全面学习C#中的多线程和异步编程,文中部分内容摘抄自一位前辈的网站:网址链接,为了更便于理解和学习,本人还在个别地方做了一

    2023年04月08日
    浏览(48)
  • Android中的多线程编程与异步处理

    在移动应用开发中,用户体验是至关重要的。一个流畅、高效的应用能够吸引用户并提升用户满意度。然而,移动应用面临着处理复杂业务逻辑、响应用户输入、处理网络请求等多个任务的挑战。为了确保应用的性能和用户体验,多线程编程和异步处理成为了不可或缺的技术

    2024年02月11日
    浏览(53)
  • Python小姿势 - Python的多线程编程

    Python的多线程编程 Python的多线程编程提供了一个非常简单的方法来让一个Python程序同时运行多个任务。这个方法通过创建新的线程来实现,线程可以被视为一个单独的执行流程。 为了创建一个新线程,我们需要使用Python的_thread模块中的start_new_thread()函数。它需要两个参数:

    2024年02月04日
    浏览(37)
  • 一文读懂flutter线程: 深入了解Flutter中的多线程编程

    在移动应用开发领域,Flutter已经成为了一个备受欢迎的框架,用于创建高性能、跨平台的应用程序。Flutter的一个关键特性是其能够轻松处理多线程编程,以改进应用程序的性能和响应性。本文将深入探讨Flutter中的多线程编程,包括为什么需要多线程、如何在Flutter中创建和管

    2024年01月20日
    浏览(80)
  • 如何在Python编程中应用Linux环境下的框架,以实现高效算法?

    python是一种广泛使用的编程语言,能够帮助开发人员快速开发高效的算法。与此同时,linux环境下提供了许多优秀的框架,可以进一步提高Python编程的效率。本文将介绍如何在Python编程中应用Linux环境下的框架,以实现高效算法。 一、Python和Linux环境的优势 Python是一种易学易

    2024年02月05日
    浏览(45)
  • 深入浅出Java的多线程编程——第二篇

    目录 前情回顾 1. 中断一个线程 1.1 中断的API 1.2 小结 2. 等待一个线程  2.1 等待的API 3. 线程的状态 3.1 贯彻线程的所有状态 3.2 线程状态和状态转移的意义 4. 多线程带来的的风险-线程安全 (重点) 4.1 观察线程不安全 4.2 线程安全的概念 4.3 线程不安全的原因 4.3.1 修改共享数据

    2024年02月07日
    浏览(77)
  • 编程小白的自学笔记八(python中的多线程)

     编程小白的自学笔记七(python中类的继承) 编程小白的自学笔记六(python中类的静态方法和动态方法)  编程小白的自学笔记五(Python类的方法)  编程小白的自学笔记四(正则表达式模块search函数)  编程小白的自学笔记三(Python正则表达式)  目录 系列文章目录 前言

    2024年02月16日
    浏览(48)
  • 目标检测YOLO实战应用案例100讲-面向恶劣环境下的多模态 行人识别

    目录 前言 国内外研究现状  可见光行人目标识别  红外行人目标识别 

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包