C 中的竞争条件

2024-02-18

我有以下程序(缩写)来使用线程计算每个字母在文件中出现的次数:


#define N_LETTERS 26U

#define IS_LETTER(x) (x >= 'A' && x <= 'Z')
#define HASH(x) toupper(x) - 'A'

typedef unsigned int uint;

typedef struct {
    uint nt;
    uint nc;
    char filename[128];
} Args;

Args args = {0};
char *file_contents = NULL;
uint file_size;

uint chars_per_thread;
pthread_mutex_t mutex;
uint letter_count[N_LETTERS] = {0};

void get_program_args(int argc, char **argv) {
    ...
}

uint read_file(char *filename, char **buffer) {
    ....

    return file_size;
}

void *count_letters(void *arg) {
    uint start = *((int *)arg);
    uint end = (start + chars_per_thread) >= file_size ? file_size : (start + chars_per_thread);
    uint count[N_LETTERS] = {0};

    for (uint i = start; i < end; i++) {
        char c = toupper(file_contents[i]);

        if (IS_LETTER(c)) {
            count[HASH(c)]++;
        }
    }

    pthread_mutex_lock(&mutex);
    for (int i = 0; i < N_LETTERS; i++) {
        letter_count[i] += count[i];
    }
    pthread_mutex_unlock(&mutex);

    return NULL;
}

float letter_sum() {
    ...
    return sum;
}

void print_letter_count() {
...
}

int main(int argc, char **argv) {
    uint chars_counted = 0;

    get_program_args(argc, argv);
    file_size = read_file(args.filename, &file_contents);

    pthread_mutex_init(&mutex, NULL);

    pthread_t *threads = malloc(args.nt * sizeof(pthread_t));
    if (threads == NULL) {
        printf("Error allocating memory. \n");
        exit(EXIT_FAILURE);
    }

    chars_per_thread = (file_size / args.nt) > args.nc ? args.nc : (file_size / args.nt);

    while (chars_counted < file_size) {
        for (int i = 0; i < args.nt; i++) {
            uint start = chars_counted;

            if (start >= file_size)
                break;

            pthread_create(&threads[i], NULL, count_letters, &start);

            chars_counted += chars_per_thread;
        }

        for (int i = 0; i < args.nt; i++) {
            pthread_join(threads[i], NULL);
        }
    }

    print_letter_count();

    pthread_mutex_destroy(&mutex);
    free(threads);
    free(file_contents); // free allocated memory

    return 0;
}

每次我使用超过 1 个线程运行程序时,我都会得到不同的答案,看起来好像我有竞争条件,但我找不到它。有人能帮我吗?

我尝试使用互斥锁来修复它,但仍然存在相同的问题。


不知道为什么@yano 没有将他们的评论作为答案,但这就是问题所在。你传递一个指针到start当你启动每个线程时,然后你去改变它的值start当该线程正在尝试读取它时!您需要一个起始值数组,并将一个指针传递给该线程自己的起始值的个人副本(该副本不会更改)。

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

C 中的竞争条件 的相关文章

  • MVC Core IActionResult 含义

    什么是IActionResult 我尝试查看 MSDN 和其他网站 但需要通用 常见 易于理解的答案 MSDN IActionResult https learn microsoft com en us dotnet api microso
  • C++ 模板中的名称查找

    我有一些 C 代码 如果没有 fpermissive 选项 就无法再编译 这是我无法分享的专有代码 但我认为我已经能够提取一个简单的测试用例来演示该问题 这是 g 的输出 template eg cpp In instantiation o
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • 将指针转换为浮点数?

    我有一个unsigned char 通常 这指向一块数据 但在某些情况下 指针就是数据 即 铸造一个int的价值unsigned char 指针 unsigned char intData unsigned char myInteger 反
  • 使用静态类型代替变量

    当您的项目不使用命名空间时 有什么方法可以告诉编译器使用静态类型而不是变量吗 例如 我有一个名为 User 的类 它具有各种静态和非静态方法 假设调用了其中一个静态方法GetUser 我想称之为User GetUser 方法来自一个方法 该
  • 使用 Selenium for C# 登录 Facebook

    我一直在使用 Selenium C 框架并尝试进行 facebook 登录 但没有任何运气 这是我到目前为止得到的 基于这篇文章 使用 Selenium 测试 Facebook Connect 应用程序 https stackoverflo
  • 基于 MS Bot Framework 中的响应分支对话框/表单

    我们正在尝试使用 MS Bot Framework 但尚未完全弄清楚如何实现此场景 我们有一个 LUIS 对话框 类型 它工作正常并且经过适当的培训 以常见的三明治为例 LUIS 意图寻找的基本内容是用户询问订单状态 如果问题中提供了订单号
  • 具有多重继承的类的 sizeof

    首先 我知道 sizeof 取决于机器和编译器的实现 我使用的是 Windows 8 1 x64 gcc 5 3 0 没有标志传递给编译器 我从大学讲座中得到了以下代码 include
  • 获取给定EntityType的导航属性

    我在用VS2010 EF4 0 需要如下功能 private string GetNaviProps Type entityType eg typeof Employee NorthwindEntities en new Northwind
  • 在不使用 Thread.Sleep c# 的情况下延迟发送电子邮件

    我有一个 for 循环 它循环并每个循环发送一封电子邮件 现在我正在使用 thread sleep 但我希望用户仍然能够与程序交互 只需取消该循环即可 是否可以在不使用 thread sleep 的情况下做到这一点 您是否在 UI 线程上运
  • 如何用C++解析复杂的字符串?

    我试图弄清楚如何使用 解析这个字符串sstream 和C 其格式为 string int int 我需要能够将包含 IP 地址的字符串的第一部分分配给 std string 以下是该字符串的示例 std string 127 0 0 1 1
  • 为什么 std::ranges::filter_view 对象必须是非常量才能查询其元素?

    include
  • Qt:将拖放委托给子级的最佳方式

    我在 QWidget 上使用拖放 我重新实现了 DragEnterEvent dragLeaveEvent dragMoveEvent 和 dropEvent 效果很好 在我的 QWidget 中 我有其他 QWidget 子级 我希望它们
  • 如何从代码隐藏中向我的 div 添加点击事件?

    如何从代码隐藏中向我的 div 添加点击事件 当我点击 div 时 会出现一个消息框 其中显示 您想删除它吗 并在框中显示 是 或 否 全部来自后面的代码 while reader Read System Web UI HtmlContro
  • C 中什么函数可以替换字符串中的子字符串?

    给定一个 char 字符串 我想查找所有出现的子字符串并将其替换为备用字符串 我没有看到任何简单的函数可以实现这一点
  • 需要使用 openssl 加密和解密文件的示例 C 代码

    我正在用 Linux C 编写代码 我需要使用以下命令来加密和解密文件 openssl 目前 我使用系统命令 des3 e nosalt k 0123456789012345 in inp file out out file 进行加密 使用
  • 在 try catch 块中返回到 catch 内是否不好?这是很好的做法

    在 try catch 块中从 C 中的 catch 块返回值是不好的做法吗 try Some code return 1 catch return 0 哪种使用 try catch 的方法是好的做法 不需要 只要返回的值是你想要的 你可以
  • 如何将 Metro 应用部署到桌面?

    我正在尝试将我的 C 应用程序部署到我的 Windows 8 Metro 桌面 我可以在 bin 文件夹中看到部署的文件 但是当我尝试打开它们时 出现以下错误 该应用程序只能在 AppContainer 的上下文中运行 我检查了属性上下文菜
  • C/C++ 通过 Android NDK 在 JNI 中看不到 Java 方法

    我正在尝试从使用 NDK 构建的 C 类文件调用 Java 方法 它不断抛出常见的 未找到非静态方法 错误并导致整个 Android 应用程序崩溃 下面的代码片段 有些东西可能不需要 但我按原样保留它们 因为焦点 问题在于refreshJN
  • 如何向 ItemsControl 中的 WPF 按钮添加相同的命令

    如何将命令添加到 wpf 按钮 该按钮是ItemsControl并正在修改ItemsSource itself 这是我的 XAML

随机推荐