草庐IT

c++ - 共享列表、多个条件、一个或多个条件变量?

coder 2024-02-25 原文

假设您有一个列表:

class CLIENTS
{
public:

    CLIENTS();
    ~CLIENTS();

    bool addClient();
    bool removeClient();
    bool getDataFromClientObj(unsigned int id);
    bool storeDataInClientObj(unsigned int id);
private:

    // vector, that contains all the clients
    boost::ptr_vector<CLIENTOBJ> clients;

    // mutex for the client-list
    boost::mutex mutex;
};

进一步考虑,getDataFromClientObj() 获取共享锁(互斥锁,私有(private)锁)。 除此之外,您还希望能够通过 getDataFromClient() 从客户端获取数据。

如果客户端在其队列中根本没有数据,getDataFromClient() 将等待该客户端的条件变量,直到它有新数据要读取。

好吧,这是我的问题:
只要 getDataFromClient();等待,(因为这是一个多读者/单作者列表),我无法添加新客户端或删除客户端,因为 getDataFromClient() 持有互斥锁。

如果您有一个列表,您将如何准确解决该场景,该列表应该是线程安全的 + 等待特定客户端的条件变量 + 在等待客户端时,能够删除或添加其中包含的任何客户端名单?

所以这里又是事实:

  • 线程安全列表(多个读者/单个作者)
  • 能够随时添加/删除客户
  • 能够专门为每个客户端等待一个(特定的)条件(一个客户端可能已经在他自己的队列中存储了新数据,而另一个没有;然后 getDataFromClient() 将等待直到有新数据被读取)

我认为的问题是,鉴于每个客户端都有一个条件(伪代码:if(clientsqueue.isEmpty() -> wait)必须有多个条件变量(我错了吗?)

更多信息:
操作系统:Windows 7
语言:C++
编译器VS2010

最佳答案

您的设置非常糟糕。您有一个由 Clients 类表示的表,以及多个 CLIENTOBJ 实例,每个实例都充当表的一行,id 充当首要的关键。然而,据我了解,每个客户端实际上是一个数据队列。

数据库使用的模型可以粗略地描述为将对数据的任何访问委托(delegate)给数据库中的专用事件(线程或进程),并使用 SQL 向其发送命令。同步问题是通过事务和 SQL 子句处理的(如果所寻找的 id 不存在,则更新可能不会影响任何行,但该命令不会失败,它只会返回 0 行更新) .在您的情况下,类似的模型可能会很有趣:只有一个全局互斥锁来表示事务,每个线程锁定整个数据结构,对其进行操作,然后解锁。但是,这可能不是很有效。

异步等价物是让每个命令返回一个 std::future 而不是真正的结果。从那时起,线程只需要等待 future,并在它完成(或因异常而中断)时对其进行操作。

Clients 实例中,任何方法调用都被转换为futurepromise。 promise 被推送到 promise 队列,调用线程要么从方法调用中获取 future ,要么立即等待它。

从数据库进程的角度来看,这是一项顺序工作:您有一个 promise 队列,所有其他线程将数据与它必须去的客户端 ID 捆绑在一起推送到该队列。然后数据库线程按顺序满足生成的 promise :

  • 创建一个新客户
  • 删除一个客户
  • 如果它是一个存储,数据库线程检查是否有任何读取挂起,并满足它,或者只是将该数据放入客户端队列
  • 如果是读取并且有数据,则从客户端队列中将其拉出并交给线程,或者将其推送到客户端的挂起读取队列,以便稍后在数据可用时满足。

通过上述解决方案,分离了所有依赖项并简化了任务。

您也可以为每个 CLIENTOBJ 分配一个线程。然后 DB 线程变成一个分类线程,它简单地将 promise 分发给每个客户端。每个客户端都拥有给定 id 的待处理读取和数据队列,因此在处理 promises 时不涉及锁。

每个队列都必须用一个互斥锁保护,这意味着主 promise 队列有 1 个互斥锁,每个客户端 promise 队列有 1 个互斥锁,条件变量与使用 Clients 方法的线程一样多.

更新:

我的回答最初提出以下建议:

In other words, you could replace the future/promise mechanism by a simple condition variable associated to each non DB threads (future and promise are probably implemented using a cond. variable, but here you would save the creation and destruction overhead).

但它对 CLIENTS 对象的使用方式做了一些隐含的假设。最安全的道路确实是 std::future 道路。

关于c++ - 共享列表、多个条件、一个或多个条件变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15531358/

有关c++ - 共享列表、多个条件、一个或多个条件变量?的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  8. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  9. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  10. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

随机推荐