我正在通过两种方法维护其他人使用多线程的代码:
1: ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ReadData), objUpdateItem)
2: Dim aThread As New Thread(AddressOf LoadCache)
aThread.Start()
但是,在双核机器上,我只有 50% 的 CPU 利用率,而在启用了超线程的双核机器上,我只有 25% 的 CPU 利用率。
显然线程非常复杂,但这种行为似乎表明我不理解一些简单的基本事实?
更新
不幸的是,代码太复杂了,无法发布在这里,但出于引用目的,大致是发生了什么......我有大约 500 个帐户,其数据从数据库加载到内存缓存中......每个帐户单独加载,该进程首先调用一个长时间运行的存储过程,然后对返回的数据进行操作和缓存。所以,在这种情况下线程化的要点是确实存在瓶颈击中数据库(即:线程将空闲长达 30 秒以等待查询返回),因此我们线程化以允许其他人开始处理他们从 Oracle 收到的数据。
所以,主线程执行:
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ReadData), objUpdateItem)
然后,ReadData() 继续执行(正好一次):
Dim aThread As New Thread(AddressOf LoadCache)
aThread.Start()
这是在递归函数中发生的,因此 QueueUserWorkItem 可以执行多次,然后通过 aThread.Start 依次执行恰好一个新线程
希望这能让您对事情的发生有一个体面的了解。
那么,在这种情况下,这是否应该在理论上固定两个核心,而不是在一个核心上以 100% 的速度最大化,而另一个核心基本上处于空闲状态?
最佳答案
该代码启动一个线程,该线程将执行某项操作。要使多个核心工作,您需要启动多个线程并让它们都忙碌。启动一个线程来做一些工作,然后让你的主线程等待它不会更快地完成任务。通常在后台线程上启动长时间运行的任务,以便 UI 保持响应,这可能是这段代码的目的,但它不会使任务完成得更快。
@Judah Himango - 我曾假设这两行代码是如何在程序的两个不同位置实现多线程的示例。也许 OP 可以澄清是否是这种情况,或者这两行是否真的在一个方法中。如果它们是一种方法的一部分,那么我们将需要查看这两种方法的实际作用。
更新:
这听起来确实应该最大化两个核心。递归调用 ReadData() 是什么意思?如果每个新线程仅在其结束时或接近结束时调用 ReadData 以启动下一个线程,那么这可以解释您所看到的行为。
我不确定这实际上是个好主意。如果存储过程需要 30 秒来获取数据,那么它可能会在数据库服务器上放置一个公平的负载。并行运行它 500 次只会让事情变得更糟。显然我不知道你的数据库或数据,但我会考虑提高存储过程的性能。
如果多线程确实看起来像前进的方向,那么我将在主线程上有一个循环,为每个需要加载的帐户调用一次 ThreadPool.QueueUserWorkItem。我还将删除显式线程创建并仅使用线程池。这样一来,您就不太可能因创建过多线程而导致本地机器饿死。
关于c# - 多核机器上的多线程没有最大化 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1127004/