pthread 竞争条件,可疑行为

2023-12-24

我编写了以下代码来演示同一进程的两个线程之间的竞争条件。

`

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int c = 0;
void *fnC()
{
    int i;
    for(i=0;i<10;i++)
    {   
        c++;
        printf(" %d", c); 
    }   
}


int main()
{
    int rt1, rt2;
    pthread_t t1, t2; 
    /* Create two threads */
    if( (rt1=pthread_create( &t1, NULL, &fnC, NULL)) )
        printf("Thread creation failed: %d\n", rt1);
    if( (rt2=pthread_create( &t2, NULL, &fnC, NULL)) )
        printf("Thread creation failed: %d\n", rt2);
    /* Wait for both threads to finish */
    pthread_join( t1, NULL);
    pthread_join( t2, NULL);
    printf ("\n");
    return 0;

}

`

我运行了这个程序,并预计两个线程之间会出现竞争条件(但是,我知道竞争条件的可能性非常小,因为线程主函数非常小)。 我运行了 50000 次。以下是输出,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - 49657 times (no race condition)
1 3 4 5 6 7 8 9 10 11 2 12 13 14 15 16 17 18 19 20 - 244 times (race condition occurs)
2 3 4 5 6 7 8 9 10 11 1 12 13 14 15 16 17 18 19 20 - 99 times (race condition occurs)

问题是, 当输出 2 中出现竞争条件时,线程 1 打印 1 并被换出处理器,线程 2 进入。它开始工作,在线程 2 打印 11 后,它被换出,线程 1 进入。它必须打印12,而是打印 2(实际上应该缺少 2)。我不知道怎么办。请帮助我理解这里发生了什么。


你正在以 C 思维方式思考,但如果你想考虑竞争条件,你必须在较低的层面上思考。

在调试器中,您通常在单行代码上设置断点,并且可以通过单步执行程序来观察每行代码的执行情况。但这不是机器的工作方式,机器可能会为每一行代码执行多条指令,并且线程可以在任何地方中断。

让我们看看这一行。

printf(" %d", c);

在机器代码中,它看起来像这样:

load pointer to " %d" string constant
load value of c global
# <- thread might get interrupted here
call printf

因此,这种行为并不意外。您必须加载的值c在你打电话之前printf,所以如果线程被中断的话always有机会c已经过时了printf做任何事。除非你做点什么来阻止它。

修复竞争条件:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int c = 0;
void *func(void *param)
{
    int i;
    for (i=0; i<10; i++) {
        pthread_mutex_lock(&mutex);
        c++;
        printf(" %d", c);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

什么是volatile do?

问题中的代码可以转换为汇编代码,如下所示:

load the current value of c
add 1 to it
store it in c
call printf

不需要重新加载c在它递增之后,因为 C 编译器可以假设除了当前线程之外没有其他人(没有其他线程或设备)更改内存。

如果你使用volatile,编译器将严格保留每个加载和存储操作,并且程序集将如下所示:

load the current value of c
add 1 to it
store it in c
# compiler is not allowed to cache c
load the current value of c
call printf

这没有帮助。实际上,volatile几乎没有帮助。大多数C程序员不明白volatile,并且对于编写多线程代码几乎没有用处。对于编写信号处理程序、内存映射IO(设备驱动/嵌入式编程)很有用,对于正确使用setjmp/longjmp.

脚注:

编译器无法缓存以下值c打电话给printf,因为据编译器所知,printf可以换c (c毕竟是一个全局变量)。有一天,编译器可能会变得更加复杂,它可能知道printf没有改变c,因此程序可能会崩溃得更严重。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pthread 竞争条件,可疑行为 的相关文章

  • 带有 ASP.NET 按钮回发的 jQuery UI 对话框

    我的 ASP NET 页面上有一个运行良好的 jQuery UI 对话框 jQuery function jQuery dialog dialog draggable true resizable true show Transfer hi
  • copy_from_user() 错误:目标大小太小

    我正在为内核模块编写 ioctl 处理程序 我想从用户空间复制数据 当我编译禁用优化的代码时 O0 gflags 编译器返回以下错误 include linux thread info h 136 17 error call to bad
  • 非模板函数中的尾随返回类型[重复]

    这个问题在这里已经有答案了 我见过有人使用以下语法来实现函数 auto get next gt int 代替 int get next 我理解两者 并且我知道尾随返回类型语法对于使用 decltype 的模板代码很有用 就我个人而言 我会避
  • SOAP Web 服务:多台服务器,一个接口

    我有一个场景 需要任意数量的服务器来提供相同的 SOAP Web 服务 我想生成一组代理类 并能够为它们提供一个位置 以便在运行时将它们指向不同的服务器 不幸的是 看起来好像wsdl port节点 子节点wsdl service 要求对特定
  • 每个元素的 asp.net Web 表单自定义错误消息

    我创建了一个 Web 应用程序 表单 以及后端 SQL 插入和查询 目前我正在显示所有用户错误消息 div style padding 1em div
  • 维护 VS Test Project 中单元测试方法之间的上下文

    我想按顺序运行以下单元测试 使用随机数字的名称 密码等创建新客户 检索刚刚创建的客户并断言其属性包含相同的随机数 对同一用户调用 ForgotPassword 函数 并使用相同的随机数作为用户名 清楚地看到 我需要生成一次随机数 并在 3
  • 在linux中将包含word的行从一个文件复制到另一个文件

    我想复制包含某些单词的行file1 to file2 Suppose file1 ram 100 ct 50 gopal 200 bc 40 ravi 50 ct 40 krishna 200 ct 100 file2应该只有包含 ct 的
  • 从图像创建半透明光标

    是否可以从图像创建光标并使其半透明 我目前正在拍摄自定义图像并覆盖鼠标光标图像 如果我可以将其设为半透明 那就太好了 但不是必需的 销售人员喜欢闪亮的 目前正在做这样的事情 Image cursorImage customImage Get
  • ASP.NET - Crystal Report Viewer 打印按钮在 ASP.NET 中不起作用

    我正在使用 Visual Studio 2008 但我遇到了水晶报告问题 当我单击打印按钮时 它会将我带到弹出窗口 但未找到页面 弹出的网址是 http localhost aspnet client System Web 2 0 5072
  • C# 可以为控制台应用程序部分类“程序”类吗?

    我想知道是否可以将为任何控制台应用程序创建的默认 程序 类更改为部分类 我想这样做是因为我想要更好的组织 而不是将所有方法都放在按区域分类的 1 个文件中 对我来说 将某些方法类别放在单独的文件中会更有意义 我对分部类的理解是 它是多个文件
  • 运行实体框架自定义工具,它有什么作用?

    在 Visual Studio 中 当使用实体框架并为 tt 和 Context tt 文件应用运行自定义工具时 它是什么以及它有什么作用 为什么它解决数据库同步问题 有时 为什么我应该在运行 tt 之前运行它 Context tt 它被称
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • MPI - 发送和接收列

    我需要从一个进程发送矩阵列并从另一个进程接收它 我尝试运行以下程序 但得到了一个奇怪的结果 至少我这么认为 仅复制矩阵的第一个元素 某些矩阵元素会发生意外变化 include
  • 让 Windows 尝试读取文件

    我正在对 Windows 文件系统进行某种封装 当用户请求打开文件时 Windows 调用我的驱动程序来提供数据 在正常操作中 驱动程序返回缓存的文件内容 但是 在某些情况下 实际文件没有缓存 我需要从网络下载它 问题是是否有可能让 Win
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • 使用通用存储库模式和流畅的 nHibernate

    我目前正在开发一个中型应用程序 它将访问不同站点上的 2 个或更多 SQL 数据库等 我正在考虑使用类似的东西 http mikehadlow blogspot com 2008 03 using irepository pattern w
  • Centos/Linux 将 logrotate 设置为所有日志的最大文件大小

    我们使用 logrotate 并且它每天运行 现在我们遇到了一些情况 日志显着增长 阅读 gigabaytes 并杀死我们的服务器 所以现在我们想为日志设置最大文件大小 我可以将其添加到 logrotate conf 中吗 size 50M
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen

随机推荐

  • Laravel - 未定义的偏移量 0 - collection.php

    我正在编写一个网络应用程序 后端是一个基于 Laravel 4 的 RESTFul 应用程序 我在使用特定控制器时遇到问题 BedsController php class BedsController extends BaseContro
  • RPY2:导入程序因 .Renviron 失败

    这是使用时应该发生的事情rpy2 robjects packages importr对于基础 R 包 例如stats gt gt gt from rpy2 robjects packages import importr gt gt gt
  • 量角器 - 描述未定义

    我正在使用 Protractor js 进行测试 当我尝试使用运行测试用例时 量角器 e2e main test spec js 我的conf js An example configuration file exports config
  • DatePicker 不更新 Android 中的 Textview

    当选择某个日期的日期选择器时 我试图更新文本视图 但它的textview 没有更新 我正在使用两个日期选择器来更新两个不同的文本视图 这是我更新 TextView 的代码 public class SearchingActivity ext
  • wxPython CheckListBox 与 HTML

    我正在使用 wxPython 创建一个 GUI 应用程序 现在我正在使用 wx CheckListBox 来显示带有复选框的选项 但我希望使用 HTML 来格式化 CheckListBox 中的文本 解决这个问题的最佳方法是什么 Repla
  • 如何滚动重启一群杂种集群

    任何人都知道一种通过 Capistrano 以 滚动 方式重新启动杂种集群的好方法 例如一次一个杂种 如果每个人都有一点等待时间 让杂种也能加载 Rails 应用程序 那就太好了 我已经做了一些搜索 但没有找到太多 所以在我自己深入研究 m
  • 我可以使用 boost 库来执行跨平台应用程序吗?

    boost c 库中是否有任何 WinAPI WinExec 模拟 我需要从我的程序运行可执行文件 并将参数传递给它 我应该为此使用任何其他跨平台库 还是自己处理我的程序编译的操作系统 重要的 请参阅末尾的 POSIX 系统更新
  • 为什么我会收到有关此代码示例的警告?什么才是正确的呢?

    我正在学习一些 C 并且正在阅读scanf from 本教程 http www tutorialspoint com c standard library c function scanf htm其中包含以下代码块 include
  • WCF NetTcpBinding 缓冲与流性能问题

    我编写了一个 WCF 服务 该服务应该使用 Streamed TransferMode 转换任何大小的文件NetTcpBinding and System IO Stream object 在运行性能测试时 我发现了明显的性能问题 然后我决
  • 如何设置带空格的环境变量?

    我需要使用批处理文件设置环境变量的值 我为此编写了脚本 echo off set value Hello world setx M srijani srijani value 它给出了错误 ERROR Invalid syntax Defa
  • 重命名字典键

    有没有一种方法可以重命名字典键 而无需将其值重新分配给新名称并删除旧名称键 并且不迭代 dict 键 值 的情况下OrderedDict https docs python org 3 library collections html co
  • JPA更新多对多删除记录

    我在两个实体之间有 ManyToMany 关系 当我在拥有方执行更新时 JPA 似乎从我的数据库中删除了所有链接记录并重新插入它们 对我来说这是一个问题 因为我有一个在删除记录之前触发的 MySQL 触发器 关于如何解决这个问题有什么想法吗
  • .NET 进程间通信的最佳选择是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我应该使用命名管道还是 NET Remoting 与计算机上正在运行的进程进行通信 WCF是最好的选择 它支持许多不同的传输机制 https l
  • 是否可以在 c/c++ 中的 double 类型(8 字节)变量中存储 8 个字符(每个字符 1 字节)?

    我正在将一些旧版 Fortran77 代码迁移到 C C 在Fortran77代码中 如果从文件中读入8个字符 则可以将它们存储在real 8类型的变量中 没有问题 是否可以在 C 或 C 中做类似的事情 如果是这样 我该怎么做 我无法在互
  • 标签指向 PHP 动态生成的图像?

    是否可以将图像重定向到动态生成的图像 使用 PHP 我有一个动态创建的图像 它有一个扩展名 PHP 显然 并且该服务器不在我的控制之下 所以我想将 somename jpg 在我的服务器上 重定向到 remoteserver dynamic
  • Rails 4 - 当前布局的名称?

    我找到了许多关于 Rails 3 的资源 但没有找到关于 Rails 4 的资源 为了保持干燥 我们有一个定义一些元标记的方法 我想将布局包含在title param app controllers application controll
  • 在 Google bigquery 中转换数据 - 提取文本、将其拆分为多列并旋转数据

    我在大查询中有一些博客数据 我需要对其进行转换以使其更易于使用和查询 数据如下 我想提取并转换数据在 Results 之后的大括号内 蓝色 数据的形式为 d PQ KL d 结果数组中可以有 1 20 多个条目 我只对前 16 个条目感兴趣
  • ClassNotFoundException:尝试从命名空间“FOS\UserBundle”加载类“FOSUserBundle”

    在 Windows 10 上使用 WampServer 我按照官方文档通过 Symfony 安装 Sonata User Bundle 我收到以下错误消息 1 1 ClassNotFoundException 尝试加载类 FOSUserBu
  • 有没有办法在 Scala 中为泛型类型变量设置默认值?

    我想为变量设置一个默认值 但我的 Scala 编译器说 Error 20 16 unbound placeholder parameter val p T 这是代码 object InverseFunctionsExample extend
  • pthread 竞争条件,可疑行为

    我编写了以下代码来演示同一进程的两个线程之间的竞争条件 include