是否可以从父线程访问/更新子线程的资源?

2024-05-04

我正在用 C 语言进行套接字编程,并且对多线程完全陌生。

这是我的场景,我需要一个父线程从套接字读取数据(可以说..)并将其排队到其子线程的队列中。这里的问题是,如何更新子线程的队列 -具体来自父线程。


支持多个生产者和消费者的线程安全队列。

MtQueue.h:

#ifndef MtQueue_H
#define MtQueue_H

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

// A fixed-size circular buffer.
typedef struct {
   pthread_mutex_t mutex;
   pthread_cond_t cond;
   int done;
   int empty;
   int full;
   size_t max;
   size_t next_insert;
   size_t next_read;
   void** buf;
} MtQueue;

// Returns NULL and sets errno on error.
// Free the queue with MtQueue_delete when done.
MtQueue* MtQueue_new(size_t max);

// Returns 0 and sets errno on error.
// Destroy the queue with MtQueue_destroy when done.
int MtQueue_init(MtQueue* q, size_t max);

// Inverse of MtQueue_new.
// Only call when the queue is no longer in use.
void MtQueue_delete(MtQueue* q);

// Inverse of MtQueue_init.
// Only call when the queue is no longer in use.
void MtQueue_destroy(MtQueue* q);

// Initiates shutdown of the queue.
// You must ensure that no there are no pending call to enqueue before this is called.
// You must ensure not to call enqueue once this is called.
void MtQueue_done(MtQueue* q);

// Returns the oldest item from the queue (via a parameter) and returns 1.
// If the queue is empty and done, returns 0.
// If the queue is empty and not done, waits until that changes.
int MtQueue_dequeue(MtQueue* q, void** pp);

// Adds the argument to the queue.
// If the queue is full, waits until that changes.
void MtQueue_enqueue(MtQueue* q, void* p);

#endif

MtQueue.c:

#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>

#include "MtQueue.h"

MtQueue* MtQueue_new(size_t max) {
   MtQueue* q = malloc(sizeof(MtQueue));
   if (!q)
      goto Error1;

   if (!MtQueue_init(q, max))
      goto Error2;

   return q;

Error2:
   free(q);
Error1:
   return NULL;
}

int MtQueue_init(MtQueue* q, size_t max) {
   void** buf = malloc(sizeof(void*) * max);
   if (!buf)
      goto Error1;

   errno = pthread_mutex_init(&(q->mutex), NULL);
   if (errno)
      goto Error2;

   errno = pthread_cond_init(&(q->cond), NULL);
   if (errno)
      goto Error3;

   q->done = 0;
   q->empty = 1;
   q->full = 0;
   q->max = max;
   q->next_insert = 0;
   q->next_read = 0;
   q->buf = buf;
   return 1;

Error3:
   pthread_mutex_destroy(&(q->mutex));
Error2:
   free(buf);
Error1:
   return 0;
}

void MtQueue_delete(MtQueue* q) {
   MtQueue_destroy(q);
   free(q);
}

void MtQueue_destroy(MtQueue* q) {
   assert(q->empty);
   free(q->buf);
   pthread_cond_destroy(&(q->cond));
   pthread_mutex_destroy(&(q->mutex));
}

void MtQueue_done(MtQueue* q) {
   pthread_mutex_lock(&(q->mutex));
   q->done = 1;
   pthread_cond_signal(&(q->cond));
   pthread_mutex_unlock(&(q->mutex));
}

int MtQueue_dequeue(MtQueue* q, void** pp) {
   pthread_mutex_lock(&(q->mutex));
   while (q->empty && !q->done)
      pthread_cond_wait(&(q->cond), &(q->mutex));

   int dequeued;
   if (q->empty) {
      // q->done && q->empty is true.
      // We are completely done.
      dequeued = 0;
   } else {
      *pp = q->buf[ q->next_read ];
      q->next_read = ( q->next_read + 1 ) % q->max;
      q->empty = q->next_read == q->next_insert;
      q->full = 0;
      dequeued = 1;
   }

   pthread_cond_signal(&(q->cond));
   pthread_mutex_unlock(&(q->mutex));
   return dequeued;
}

void MtQueue_enqueue(MtQueue* q, void* p) {
   pthread_mutex_lock(&(q->mutex));
   while (q->full)
      pthread_cond_wait(&(q->cond), &(q->mutex));

   assert(!q->done);

   q->buf[q->next_insert] = p;
   q->next_insert = ( q->next_insert + 1 ) % q->max;
   q->empty = 0;
   q->full = q->next_insert == q->next_read;

   pthread_cond_signal(&(q->cond));
   pthread_mutex_unlock(&(q->mutex));
}

a.c(示例用户):

#include <errno.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "MtQueue.h"

// Producers will block if there are this many items in the queue.
#ifndef QUEUE_SIZE
#define QUEUE_SIZE 10
#endif

// The number of consumers (worker threads) to create.
#ifndef NUM_WORKERS
#define NUM_WORKERS 4
#endif

// The amount of work to generate for this test.
#ifndef NUM_JOBS
#define NUM_JOBS 40
#endif

// Simulate work using a sleep.
#ifndef SIM_WORK
#define SIM_WORK 0
#endif

#if SIM_WORK
static int msleep(long msec) {
   struct timespec ts;
   int res;

   if (msec < 0) {
       errno = EINVAL;
       return -1;
   }

   ts.tv_sec = msec / 1000;
   ts.tv_nsec = (msec % 1000) * 1000000;

    do {
       res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}
#endif

// Shared variables.
static MtQueue q;

static void* worker_func(void* worker_id_) {
   uintptr_t worker_id = (uintptr_t)worker_id_;

#if SIM_WORK
   unsigned int seed = worker_id;  // Whatever.
#endif

   uintptr_t j;
   while (MtQueue_dequeue(&q, (void**)&j)) {
      printf("[%" PRIuPTR "] Dequeued %" PRIuPTR "\n", worker_id, j);
#if SIM_WORK
      msleep( rand_r(&seed) % 1000 + 1000 );  // Simulate a 1 to 2s load.
#endif
      printf("[%" PRIuPTR "]    Finished processing %" PRIuPTR "\n", worker_id, j);
   }

   return NULL;
}

int main(void) {
   MtQueue_init(&q, QUEUE_SIZE);

   pthread_t workers[NUM_WORKERS];
   for (uintptr_t w=0; w<NUM_WORKERS; ++w) {
      if (errno = pthread_create(&(workers[w]), NULL, worker_func, (void*)w)) {
         perror(NULL);
         exit(1);
      }
   }

   for (uintptr_t j=0; j<NUM_JOBS; ++j) {
      printf("[x] Enqueuing %" PRIuPTR "...\n", j);
      MtQueue_enqueue(&q, (void*)j);
      printf("[x]    Enqueued %" PRIuPTR ".\n", j);
   }

   MtQueue_done(&q);
   printf("[x] Called done.\n");

   for (uintptr_t w=0; w<NUM_WORKERS; ++w)
      pthread_join(workers[w], NULL);

   MtQueue_destroy(&q);
   return 0;
}

如何运行示例用户:

gcc -Wall -Wextra -pedantic a.c MtQueue.c -o a -lpthread && ./a
gcc -D SIM_WORK=1 -D NUM_JOBS=20 -Wall -Wextra -pedantic a.c MtQueue.c -o a -pthread && ./a
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以从父线程访问/更新子线程的资源? 的相关文章

  • Java 套接字:可以从一个线程发送并在另一个线程上接收吗?

    这可能是一个非常基本的问题 但我很难找到答案 让一个线程写入 Socket 的输出流 而另一个线程从 Socket 的输入流读取数据 这样可以吗 编辑 这是一个与外部服务器通信的客户端应用程序 我并不是想让两个线程互相交谈 很抱歉含糊不清
  • 最新 .Net MongoDb.Driver 的连接问题

    我创建了一个 MongoLab 沙箱数据库 我与 MongoChef 连接 效果很好 我通过 Nuget 安装了 MongoDB Driver 2 2 2 我编写了一些简单的 C 演示代码 但就是无法使其工作 连接字符串是直接从 Mongo
  • 局部函数声明有什么用处吗?

    大多数像我这样的 C 程序员都曾犯过以下错误 class C int main C c declares a function c taking no arguments returning a C not as intended by m
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • 嵌入资源文件的路径

    我的资源文件中有一个图标 我想引用它 这是需要图标文件路径的代码 IWshRuntimeLibrary IWshShortcut MyShortcut MyShortcut IWshRuntimeLibrary IWshShortcut W
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • opencv中如何去除二值图像噪声?

    将图像转换为二值图像 黑白 后如果有任何噪音怎么办 我消除了那些不需要的噪音 您可以看到下图的黑色区域内有一些白噪声 我该如何去除噪声 使用opencv http img857 imageshack us img857 999 blackn
  • Visual Studio 中列表框的上移、下移按钮[重复]

    这个问题在这里已经有答案了 我正在尝试制作一个上移按钮和一个下移按钮 以移动 Microsoft Visual Studio 2012 中列表框中的选定项目 我已经在 WDF jquery winforms 和其他一些表单中看到了其他示例
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • 处理“未找到细胞”。 Excel 中的错误

    我正在使用 Excel VSTO 应用程序并使用以下代码在工作表中查找错误单元格 Excel Range rngTemp Excel Range rngErrorRange Excel Worksheet Sheet1 Excel Work
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 您对“大规模 C++ 软件设计”的看法 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 正在阅读亚马逊评论 https rads stackoverflow com amzn click com 0201633620 and ACC
  • 更改 Xamarin.Forms 应用中顶部栏和底部栏(ControlsBar、StatusBar)的颜色

    无论如何 即使后面需要特定于平台的代码 也可以更改顶部栏 蓝色的 和底部栏 黑色的 的颜色吗 我希望添加对浅色和深色模式的支持 因此我希望能够在运行时更改它 有可能的 Android Using Window SetStatusBarCol
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • valgrind 在 Raspberry Pi 上返回未处理的指令

    我最近一直在尝试在运行 Debian GNU Linux7 0 喘息 的树莓派 型号 b 上使用 valgrind 来调试分段错误 每次我在编译的 C 程序上运行 valgrind 时 都会得到类似以下内容的信息 disInstr arm
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • 连接到没有元数据的网络服务

    我想连接到此网络服务 https training api temando com schema 2009 06 server wsdl https training api temando com schema 2009 06 serve
  • 具有四个 && 的 LINQ Where 子句

    我正在尝试在Where 子句中创建一个带有4 个参数的LINQ 查询 这是一个 Windows 8 应用程序项目 我正在使用 SQLite 数据库 SQLite 实现 https github com praeclarum sqlite n
  • 使用Python的线程模块调用ctypes函数比使用多处理更快?

    我一生都无法找出这个问题的答案 我编写了一个可以执行数百次繁重计算的脚本 我有一个绝妙的主意 将这些计算任务编写为 C 然后使用 Python 的 ctypes 与它们交互 我心想 我什至可以使用并行性进一步优化它 我最初的方法是使用线程

随机推荐

  • 在命名空间内的类中使用带有运算符重载的字符串流时,“与‘operator>>’不匹配”

    我试图在命名空间内的类中重载 gt gt 运算符 但是一旦我尝试将它与字符串流一起使用 它就不起作用 这是我的代码的精炼版本 include
  • 有没有办法合并 Kusto 中两个表的数据?

    详细了解如何在 Kusto 中编写查询 我在两个具有不同角色的表中有一列 但列标题是角色 我想将数据合并到一个名为 角色 的列中 我尝试添加这个 extends Roles strcat RoleName Role 但这只是组合了数据 这是
  • 如何告诉 pytest-xdist 按顺序从一个文件夹运行测试,并并行运行其余文件夹?

    想象一下我有test unit 可以安全地并行运行并且test functional 目前还不能并行运行 有没有一种简单的方法可以说服 pytest 运行functional依次 考虑到我们正在讨论大量的测试 因此改变每个测试函数 方法将会
  • Cassandra:如何将整个表移动到另一个键空间

    我的 Cassandra 的版本信息 cqlsh 5 0 1 卡桑德拉 2 2 5 CQL 规范 3 3 1 本机协议 v4 我正在尝试将一些巨大的表 几百万行 移动到另一个键空间 除了 COPY to csv and COPY from
  • 如何在 Android 上将 SurfaceView 与 main.xml 一起使用?

    在我的项目的主课中 我有 public class MyClass extends Activity public void onCreate Bundle savedInstanceState super onCreate savedIn
  • 如何在javascript中实现deque数据结构?

    我正在用 javascript 学习数据结构 我现在的重点是如何实现双端队列 编辑 从下面的评论中我得到了有关如何实施的有用指示deque based array 有没有一个具体实施的方向deque based object使用类 我明白了
  • Symfony 不会从集合中删除实体

    我知道一般来说有很多关于这个主题的帖子 不幸的是 这些大多涉及对数据库的实际持久操作 就我而言 我在持久操作之前发生了一个问题 我有一个带有实体 学说 持久性集合的表单 您可以通过 javascript 从 DOM 中删除 对象 提交后 当
  • Vim 关闭窗口而不关闭缓冲区

    如何在不删除缓冲区的情况下关闭窗口或取消分割 A window is a viewport on a buffer In vim to manage windows it is CTRL w the leading command that
  • Python:导入错误,没有名为 urllib 的模块

    我刚刚从Linode租了一个VPS 它有python2 5和ubuntu 8 04 当我运行这个命令时python shell import urllib I get ImportError No module named urllib 可
  • 杀死应用程序后,后台获取不起作用

    我正在尝试通过后台获取从 url 获取数据 我的函数尝试获取数据 如果有新数据 它会发送本地通知 当我最小化应用程序时 后台获取会在大约 10 20 分钟后开始工作 但是当我杀死该应用程序 双击主页按钮并关闭应用程序 时 它不起作用 我等了
  • 为什么正则表达式不能使用关键字而不是字符?

    好吧 我几乎不了解 RegEx 基础知识 但为什么他们不能将其设计为使用关键字 如 SQL 而不是一些神秘的通配符和符号呢 由于正则表达式是在运行时解释 解析的 所以是为了性能吗 未编译 或者也许是为了写作速度 考虑到当您学习一些 简单 字
  • 异步 lambda 到表达式>

    众所周知 我可以将普通的 lambda 表达式转换为Expression
  • 3D 数组如何在 C 中存储?

    据我所知 C 中的数组是按行优先顺序分配的 因此 对于 2 x 3 数组 0 1 2 3 4 5 存储在内存中为 0 1 2 3 4 5 但是 如果我有一个 2 x 3 x 2 数组怎么办 0 1 2 3 4 5 and 6 7 8 9 1
  • 从左到右显示 SVG 动画

    我有两个 SVG 图像 我想将它们设置为动画 如下所示 首先显示Full Screen文本从左到右 然后用第二个 SVG 覆盖该单词Screen显示整个第二个 SVG 因此 最后我将得到第二个 svg 中的单词 Full 黑色空间 以及单词
  • CSS位置绝对和全宽问题

    我想改变 dl 下面占据全屏宽度而不更改换行和包含它的标题元素 当我尝试定位 dl 元素 参见 problematic code 部分 下面 导航获取最大宽度为 1003px 的包装器的 100 我希望它在不改变换行和标题 div 的情况下
  • Unity-3d-5 将 16:9 的图像缩放至其他分辨率

    所以我创建了一个蛇游戏 其边框是用 2d 精灵创建的 我将游戏窗口设置为 16 9 在此分辨率下图像看起来不错 然而 扩展到其他任何东西开始让游戏看起来很奇怪 我想要调整游戏窗口的大小 如何让我的精灵根据当前分辨率拉伸和收缩 我已经尝试创建
  • VS Code 和 Flutter/Dart,小部件自动完成功能不起作用

    我正在使用一些教程来学习 Flutter 而我现在正在学习的教程则使用 VSCode 事实上 与 Android Studio 相比 我更喜欢它 因为它不会使我的 Macbook 过热 到目前为止 我唯一感到沮丧的是 有很多次自动完成功能停
  • 使用 Java 中的 JTextfield (Netbeans) 使用点分隔符使输入字段自动格式化数字

    我是 Java 新手 在我的第一个 Java 程序 使用 Netbeans 中 我想添加带有点 的输入字段自动格式编号 使用 JTextfield 分隔符 这是我的简短代码 private void PayTransKeyReleased
  • 私有子网中的EKS,公共子网中的负载均衡器

    我在私有子网中运行 EKS 因此无法创建面向互联网的负载均衡器 但能够创建内部负载均衡器 有什么方法可以在公共子网中创建负载均衡器 可能是手动 并指向私有子网中 EKS 中运行的 Pod 我正在考虑创建负载均衡器链 其中外部负载均衡器将指向
  • 是否可以从父线程访问/更新子线程的资源?

    我正在用 C 语言进行套接字编程 并且对多线程完全陌生 这是我的场景 我需要一个父线程从套接字读取数据 可以说 并将其排队到其子线程的队列中 这里的问题是 如何更新子线程的队列 具体来自父线程 支持多个生产者和消费者的线程安全队列 MtQu