在C ++中执行以下操作的最佳方法是什么?虽然我目前的方法有效,但我不确定这是最好的方法:
1)我有一个大师班,其中有一些功能
2)我有一个线程在套接字上接受一些指令,然后运行master类中的一个函数
3)有许多线程可以访问master类中的各种函数
我创建了主类,然后从主服务器创建线程类的实例。线程类的构造函数传递给master的“this”指针。然后我可以在线程内部的主类中运行函数 - 即我得到一个命令来执行从线程中在主类中运行函数的操作。我有mutex等来防止种族问题。
我是否采用了错误的方式 - 似乎线程类应该继承主类,或者另一种方法是没有单独的线程类,只是让它们作为主类的函数但是变得丑陋。
答案 0 :(得分:1)
单独的线程类是很正常的,特别是如果它们具有特定的功能。我不会继承主线程。
答案 1 :(得分:1)
将this
指针传递给线程本身并不是坏事。你用它做什么可以。
this
指针就像任何其他POD-ish数据类型一样。这只是一大块。然而,this
中的内容可能比POD更多,并且传递实际上指向其成员的指针可能是所有常见原因的危险。任何时候你在线程之间共享任何东西,它都会引入潜在的竞争条件和死锁。当然,解决这些冲突的基本方法是以互斥体,信号量等形式引入同步,但这会产生序列化应用程序的惊人效果。
假设您有一个线程从套接字读取数据并将其存储到同步命令缓冲区,另一个线程从该命令缓冲区读取。两个线程都使用相同的互斥锁,这会保护缓冲区。一切都很好,对吧?
好吧,也许不是。如果您对锁定缓冲区的方式不太谨慎,您的线程可能会被序列化。据推测,您为缓冲区插入和缓冲区删除代码创建了单独的线程,以便它们可以并行运行。但是,如果你用每个插入物锁定缓冲区&每次删除,然后一次只能执行其中一个操作。只要您写入缓冲区,就无法从中读取,反之亦然。
您可以尝试对锁进行微调,使其尽可能简短,但只要您拥有共享的同步数据,就会有一定程度的序列化。
另一种方法是明确地将数据移交给另一个线程,并尽可能多地删除数据共享。例如,您的套接字代码可能会在堆上创建某种Command
对象(例如Command* cmd = new Command(...);
)并将其传递给另一个线程,而不是像上面那样写入和读取缓冲区。 。 (在Windows中执行此操作的一种方法是通过QueueUserAPC机制)。
有优点&这两种方法都有缺点。同步方法的优点是在表面上理解和实现起来有点简单,但是如果你搞砸了某些东西,那么调试起来要困难得多。切换方法可以使同步中固有的许多问题变得不可能(从而实际上使其更简单),但是在堆上分配内存需要时间。
答案 2 :(得分:1)
听起来不错。在我的服务器中,它被称为“SCB” - ServerControlBlock - 并提供对IOCPbuffer / socket池,记录器,状态/错误消息的UI访问以及所有处理程序线程需要共享的任何其他服务的访问。工作正常,我不认为它是一个黑客。
我创建了SCB,(并确保在ctor中通过它访问的所有服务都已启动并可以使用),然后创建使用SCB的线程池 - 没有令人讨厌的单一内容。
RGDS, 马丁