2009-10-06 110 views
0

我是一个中级程序员,但相对多线程的新手。 目前,我正在用类似下面这样的结构的应用程序:线程安全访问对象之间共享的数据

class Client 
{ 
    public: 
     Client(); 

    private: 
    // These are all initialised/populated in the constrcutor. 
     std::vector<struct clientInfo> otherClientsInfo; 
     ClientUI* clientUI; 
     ClientConnector* clientConnector; 
} 

class ClientUI 
{ 
    public: 
     ClientUI(std::vector<struct clientInfo>* clientsInfo); 

    private: 
     // Callback which gets new client information 
     // from a server and pushes it into the otherClientsInfo vector. 
     synchClientInfo(); 
     std::vector<struct clientInfo>* otherClientsInfo; 
} 

class ClientConnector 
{ 
    public: 
     ClientConnector(std::vector<struct clientInfo>* clientsInfo); 

    private: 
     connectToClients(); 
     std::vector<struct clientInfo>* otherClientsInfo; 
} 

有点一个人为的例子,我知道了。程序流程是这样的:

  • 客户端被构造和填充otherClientsInfo并构造clientUI和clientConnector的指针otherClientsInfo。

  • 客户端随时调用synchClientInfo()服务器与新客户端信息进行联系,解析新数据并将其推回到其他ClientsInfo或删除元素。

  • 当connectToClients()被调用但不会改变它们时,clientConnector将访问otherClientsInfo中的每个元素。

我的第一个问题是,是否我的假设是,如果两个ClientUI和ClientConnector访问otherClientsInfo的同时,将程序的炸弹,因为线程不安全的?

如果是这种情况,那么我该如何去访问其他ClientsInfo线程安全的,或许在某个对象访问它时以某种方式锁定它?

+0

什么的线程库您使用? – hirschhornsalz 2009-10-06 09:43:12

+0

我使用Qt工具包,它调用因为我在Linux/BSD 所以据我所知并行线程。从其他的答案,我想这也许是好主意 周围创建矢量一类,也许使用互斥来它 控制访问。好/坏主意? – Conor 2009-10-06 10:11:35

+0

好主意,像Pete Kirkhams的建议可能会对你最好。 – 2009-10-06 17:38:30

回答

0

如果ClientUI和ClientConnector同时访问otherClientsInfo,程序是否会因线程不安全而弹出?
是的,STL容器不是线程安全的。

如果是这种情况,那么我该如何去访问其他ClientsInfo线程安全的,或许在某个对象访问它时锁定它?
在最简单的情况下,访问共享数据周围的互斥模式......如果您有多个读者,那么您会选择更高效的模式。

+0

这是我的理解,互斥锁阻止线程访问相同功能中的数据,这是正确的吗? 也许我误解了你的答案,但是程序中发生的事情是vectorClientInfo可能同时被两个不同类型的对象访问,互斥锁会阻止一个对象访问它,而另一个对象访问它吗? 此外,您还可以点我在读者和相关的模式很好的参考的方向是什么? 谢谢你的回复。 – Conor 2009-10-06 09:56:22

+0

互斥锁是帮助您避免同时访问关键数据的工具,例如参见http://en.wikipedia.org/wiki/Mutual_exclusion – 2009-10-06 10:07:47

+0

而且是的,问题是同时访问......并且这就是锁之类的互斥锁帮你。 – 2009-10-06 10:12:16

0

clientConnector是否从与synchClientInfo()相同的线程中调用(即使它是全部回调)? 如果是这样,你根本不用担心线程安全。

如果要避免同时访问相同的数据,可以使用互斥锁来保护关键部分。对于exmample,mutexes from Boost::Thread

1

我的第一个问题是,是否我的假设是,如果两个ClientUI和ClientConnector访问otherClientsInfo的同时,将程序的炸弹,因为线程不安全的?

是的。 std::vector的大多数实现不允许并发读取和修改。 (你会知道,如果你使用one which did

如果是这样的话,那么我将如何去进行访问otherClientsInfo线程安全的,在某种程度上也许当一个对象访问它锁了吗?

无论何时只要访问矢量,您都需要至少锁定一个锁(无论是简单的互斥锁还是临界区或读/写锁)。既然你只有一个读写器,那么读/写锁就没有意义了。

然而,实际上这样做正确将得到越来越困难,因为你是暴露TE矢量其他类,因此必须揭露锁定原语也,记住,只要你使用向量来获取它。它可能是更好,以暴露addClientInforemoveClientInfo和const和非const foreachClientInfo功能,其封装在Client类的锁定,而不是由客户端浮动左右的地方所拥有的数据的不相交的位。

+0

我正在使用QT工具包,它有一个QVector类,其功能 是可重入的。我不知道是否会重入解决我的问题在 这种情况下,反而会从QVector推导或类中封装 的std ::载体,为您提供建议 与功能互斥为我提供了一个解决方案吗? – Conor 2009-10-06 10:01:30

+0

将互斥量放在所有对向量的访问中将提供一个解决方案。如果不暴露向量,那么所有访问都会发生在一个类中,因此操作它的函数会更容易。我不知道QT,所以不能真正评论它是否安全。 – 2009-10-06 10:07:07

+0

然后,只需将包装类的指针传递给ClientConnector和ClientUI的构造函数 ?我可能会采取这个想法,并将其与QVector一起使用,如果使用QT编码 ,那么使用QT的类型可能更有意义...非常感谢您的帮助。 – Conor 2009-10-06 10:16:21

0

为了确保从多个线程访问otherClientsInfo成员是安全的,你需要用互斥锁来保护它。我写了一篇关于如何直接对象在C互斥量​​关联的文章++以上的博士道博的网站:

http://www.drdobbs.com/cpp/225200269