草庐IT

linux线程同步

coder 2023-06-20 原文

我是 linux 和 linux 线程的新手。我花了一些时间在谷歌上搜索,试图了解所有可用于线程同步的函数之间的差异。我还有一些问题。

我发现了所有这些不同类型的同步,每个同步都有许多用于锁定、解锁、测试锁定等的功能。

  • gcc 原子操作
  • futexes
  • 互斥锁
  • 自旋锁
  • 序列锁
  • rculocks
  • 条件
  • 信号量

  • 我目前(但可能有缺陷)的理解是:

    信号量是进程范围的,涉及文件系统(实际上我认为),并且可能是最慢的。

    Futex 可能是互斥锁、自旋锁、序列锁和 rculock 使用的基本锁定机制。 Futex 可能比基于它们的锁定机制更快。

    自旋锁不会阻塞,从而避免上下文切换。然而,它们以消耗 CPU 上的所有周期直到释放锁(自旋)为代价来避免上下文切换。出于显而易见的原因,它们应该仅用于多处理器系统。永远不要睡在自旋锁中。

    如果作者更改了工作所基于的数据,则 seq 锁只会告诉您何时完成工作。在这种情况下,您必须返回并重复工作。

    原子操作是最快的同步调用,并且可能用于上述所有锁定机制。您不想对共享数据中的所有字段使用原子操作。当您访问多个数据字段时,您想对锁标志使用锁(互斥锁、futex、spin、seq、rcu)或单个原子操作。

    我的问题是这样的:
  • 到目前为止,我的假设是否正确?
  • 有谁知道各种选项的 CPU 周期成本?我正在为应用程序添加并行性,因此我们可以获得更好的挂机时间响应,但代价是每盒运行更少的应用程序实例。表演是最重要的考虑因素。我不想通过上下文切换、旋转或大量额外的 cpu 周期来消耗 cpu 来读取和写入共享内存。我绝对关心消耗的 CPU 周期数。
  • 哪个(如果有)锁可以防止调度程序或中断中断线程......或者我只是一个白痴,所有同步机制都这样做。什么类型的中断被阻止?我可以在锁定线程的 CPU 上阻塞所有线程或线程吗?这个问题源于我害怕中断持有非常常用函数锁的线程。我希望调度程序可能会调度任意数量的其他工作人员,这些工作人员可能会遇到这个函数,然后因为它被锁定而阻塞。在重新调度并完成具有锁的线程之前,将浪费大量上下文切换。我可以重写这个函数来最小化锁定时间,但它仍然如此普遍,我想使用一个防止中断的锁......跨所有处理器。
  • 我正在编写用户代码......所以我得到了软件中断,而不是硬件中断......对吗?我应该远离任何包含“irq”一词的函数(自旋/序列锁)。
  • 哪些锁用于编写内核或驱动程序代码,哪些用于用户模式?
  • 有没有人认为使用原子操作让多个线程在链表中移动很疯狂?我想以原子方式将当前项目指针更改为列表中的下一个项目。如果尝试成功,则线程可以安全地使用当前项在移动之前指向的数据。其他线程现在将沿着列表移动。
  • futex?有什么理由使用它们而不是互斥体?
  • 有没有比在没有工作时使用条件使线程休眠更好的方法?
  • 当使用 gcc 原子操作,特别是 test_and_set 时,我可以通过先进行非原子测试然后使用 test_and_set 确认来提高性能吗?我知道这将视具体情况而定,所以就是这种情况。有大量的工作项目,比如数千个。每个工作项都有一个初始化为 0 的标志。当线程对工作项具有独占访问权限时,该标志将为 1。会有很多工作线程。任何时候线程正在寻找工作,它们都可以非原子地测试 1。如果它们读取 1,我们肯定知道该工作不可用。如果他们读到一个零,他们需要执行原子 test_and_set 来确认。因此,如果原子 test_and_set 是 500 个 cpu 周期,因为它禁用了流水线,导致 cpu 通信和 L2 缓存刷新/填充 .... 一个简单的测试是 1 个周期 .... 那么只要我有更好的比率当遇到已经完成的工作项目时,500比1......这将是一场胜利。

  • 我希望使用互斥锁或自旋锁来严格保护我一次只希望 SYSTEM 上的一个线程(而不是 CPU)访问的代码部分。我希望谨慎使用 gcc atomic ops 来选择工作并尽量减少互斥锁和自旋锁的使用。例如:可以检查工作项中的标志以查看线程是否已经工作(0=否,1=是或正在进行)。一个简单的 test_and_set 告诉线程它是否有工作或需要继续。我希望在有工作时使用条件来唤醒线程。

    谢谢!

    最佳答案

    应用程序代码可能应该使用 posix 线程函数。我假设你有手册页所以输入

    man pthread_mutex_init
    man pthread_rwlock_init
    man pthread_spin_init
    

    阅读它们以及对它们进行操作的函数,以确定您需要什么。

    如果您正在进行内核模式编程,那么情况就不同了。您需要了解自己在做什么、需要多长时间以及调用它的上下文,才能知道需要使用什么。

    关于linux线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2594898/

    有关linux线程同步的更多相关文章

    1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

      我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

    2. 使用canal同步MySQL数据到ES - 2

      文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

    3. ruby - 如何让Ruby捕获线程中的语法错误 - 2

      我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

    4. ruby - 如何在 ruby​​ 中运行后台线程? - 2

      我是ruby​​的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp

    5. ruby - Rails 开发服务器、PDFKit 和多线程 - 2

      我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:

    6. ruby - Ruby 1.9.1 中的 native 线程,对我有什么好处? - 2

      所以,Ruby1.9.1现在是declaredstable.Rails应该与它一起工作,并且正在慢慢地将gem移植到它。它具有native线程和全局解释器锁(GIL)。自从GIL到位后,原生线程是否比1.9.1中的绿色线程有任何优势? 最佳答案 1.9中的线程是原生的,但它们被“放慢了速度”,一次只允许一个线程运行。这是因为如果线程真的并行运行,它会混淆现有代码。优点:IO现在在线程中是异步的。如果一个线程阻塞在IO上,那么另一个线程将继续执行直到IO完成。C扩展可以使用真正的线程。缺点:任何非线程安全的C扩展都可能存在使用Thre

    7. ruby - 使写入文件线程安全 - 2

      我在一个ruby​​文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}

    8. 【Linux操作系统】——网络配置与SSH远程 - 2

      Linux操作系统——网络配置与SSH远程安装完VMware与系统后,需要进行网络配置。第一个目标为进行SSH连接,可以从本机到VMware进行文件传送,首先需要进行网络配置。1.下载远程软件首先需要先下载安装一款远程软件:FinalShell或者xhell7FinalShellxhell7FinalShell下载:Windows下载http://www.hostbuf.com/downloads/finalshell_install.exemacOS下载http://www.hostbuf.com/downloads/finalshell_install.pkg2.配置CentOS网络安装好

    9. Linux磁盘分区中物理卷(PV)、卷组(VG)、逻辑卷(LV)创建和(LVM)管理 - 2

      文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分

    10. ruby - 如何在 Ruby 中获取 linux 系统信息 - 2

      如何在Ruby中获取linux系统(这必须适用于Fedora、Ubuntu等)的软件/硬件信息? 最佳答案 Chef背后的优秀人才,拥有一颗名为Ohai的优秀gemhttps://github.com/opscode/ohai以散列形式返回系统信息,例如操作系统、内核、规范、fqdn、磁盘、空间、内存、用户、接口(interface)、sshkey等。它非常完整,非常好。它还会安装命令行二进制文件(也称为ohai)。 关于ruby-如何在Ruby中获取linux系统信息,我们在Stack

    随机推荐