- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我需要实现一种机制,该机制具有一个数据结构(此刻为队列),其中包含一个待处理的请求对象的列表,这些对象在使用时由不同的线程标记,在线程使用完该线程后将其删除。
在任何给定时间,此数据结构中最多可以包含数千个项目,并且N个线程将从中接收请求(本质上将其标记为“已接受”),然后当线程完成时,它将在结构中找到相同的请求,并且去掉它。
现在,我想知道C++ STL队列在执行此操作方面是否有效,以及在需要将其从队列中删除时是否必须再次查找同一项目?
我不希望这种数据结构被线程同步机制锁定太长时间,因为线程正在其中寻找某项。这可能会锁定我的整个程序。 (该程序必须具有很高的性能和速度)
谁能建议如何在多线程环境中最好地实现这一点,以使该结构在需要执行搜索时不会长时间锁定?
最佳答案
您可能正在关注什么不是您设计中最困难的部分。
如果队列是没有任何优先级的FIFO,那么您的访问器将是push_back()和pop_front()-即使您不麻烦使用比较交换(CAS)语义,但坚持使用a简单的互斥/关键部分。如果您需要对流量进行优先级排序的能力,则事情会变得更加艰难。如果您确实使用CAS锁定,那么(无论如何在Windows上)您都无法在boost::thread的shared_mutex上进行改进,而不会花费太多时间来进行这部分编码。不确定非Windows实现。
此问题最复杂的部分通常是发信号通知空闲的工作程序线程来接管新工作。在queue.front()为非空之前,您不能让它们循环,因此您需要一种方法来确保踢出正确数量的空闲线程来拾取排队的项目。当工作线程空闲时,它可以检查是否有新工作,如果不是,则执行,否则队列状态需要设置为空闲,以便下一个push_back导致“唤醒”踢,以重新启动工作线程池。该区域必须对所有非致命异常都具有100%的鲁棒性,否则您的流程将变得一片漆黑。
您是在管理自己的线程还是在使用内置线程池?您是否打算拥有一个动态大小的线程池,或者只是生成N个线程(可能是可配置的)并使它们运行直到进程退出?
绝对有工作线程执行工作项过程的日志记录。了解谁在其生命周期的任何阶段都拥有工作项至关重要。停止/开始工作,以及工作项摘要和时间安排将很有用。如果日志记录很慢,则通过即发即弃队列将其推送到单独的线程,但是您必须注意那里的延迟,这会降低日志的实用性。如果您确实需要从外部操纵进行中的工作项的能力,则从挂起的工作队列中选择一个单独的结构-通过线程索引并显示当前状态/开始时间并进行单独锁定的进行中的工作项,听起来是个好主意。此结构将是O(线程数),因此小于“待处理”队列,因此,如果长时间运行的结果操作在结构锁之外完成,则扫描它就不会成为瓶颈。
关于性能-您的工作线程将要做什么?如果工作项需要长期运行,执行大量I/O或其他昂贵的操作,那么队列交互并不是您的性能瓶颈,因此对该区域进行过度优化相对而言是无济于事的。在您的设计中考虑整个系统的性能,而不仅仅是一小部分。
这仅适合初学者。祝您好运,这不是一个易于健壮设计的系统。
[编辑]基于工作项描述。
解析应该很快(尽管可能涉及昂贵的源数据检索-很难说吗?),而数据库访问则要少一些。听起来,调优数据库可能是您在性能方面最大的收获。如果您对此无能为力,则只需要尽可能减少设计中的慢速DB。如果您可以选择执行异步数据库访问,则工作线程可以执行足够的工作来启动数据库调用,然后完成回调中的工作,从而允许在工作线程上启动其他工作。如果没有异步数据库访问,那么如果没有其他间接方法(您的主工作线程不等待数据库调用完成内联),将很难实现可靠的请求超时。您需要使主工作线程与对数据库的依赖脱钩,除非您可以信任数据库及时返回或出错。也许对数据库请求有一些可配置的或特定于工作项的超时? DB API库通常允许这样做。
您的超时监控器需要保持对工作项状态的了解。可能在您的工作项上使用一些虚拟的Cancel()方法,以确保灵活地清理超时项目。
关于c++ - 多线程访问的高效结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3634589/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!