我对以下C#代码的线程激活顺序感到困惑。它创建10个线程,随机启动它们,每个线程模拟以执行耗时的工作10次,如果您检查了调试输出,则该线程似乎不是不会随机拾取的,请参见下面的输出示例,请注意,请注意TREES#3,#5,#6总是被拾取,当#3#5#6完成时,#10#2#8总是被捡起等等...(我知道设计很糟糕,请专注于现象)
我的PC具有i7-7820HQ CPU,它具有4个内核,并且正在运行Windows 10。
有人可以解释为什么没有随机选择这些线程,并且似乎以某种方式分组。
非常感谢!
----调试输出----
线程#10获得了锁,并为任务#0工作线程#5获得了锁,并为任务#0工作线程#3获得了锁,并为任务#0工作线程#6获得了锁,并为任务#0工作线程#5获得了锁,并为任务1工作线程#3获取了锁,并为任务#1工作线程#6获取了锁,并为任务#1工作...线程#5获取了锁,并为任务#9工作线程#3获取了锁,并为任务#9工作线程#6获取了锁,并为任务#9工作...线程#8获得了锁,并为任务#0工作线程#2获取了锁,并为任务#0工作线程#8获得了锁,并为任务1工作线程#2获取了锁,并为任务#1工作线程#10获取了锁,并为任务#1工作...线程#8获取了锁,并为任务#9工作线程#2获取了锁,并正在为任务9工作线程#10获取了锁,并为任务#9工作...
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static Hashtable _sharedBetweenThreads = new Hashtable();
static void Main(string[] args)
{
Random random = new Random(DateTime.Now.Second);
var startOrders = new int[10];
for (int i = 0; i < startOrders.Length; i++)
{
startOrders[i] = i;
}
//shuffle the array
for (int i = startOrders.Length - 1; i >= 0; i--)
{
int j = random.Next(0, i);
int temp = startOrders[i];
startOrders[i] = startOrders[j];
startOrders[j] = temp;
}
Thread[] threads = new Thread[startOrders.Length];
for(int i = 0; i < startOrders.Length; i++)
{
threads[i] = new Thread(new ThreadStart(ThreadProc));
}
for (int i = 0; i < startOrders.Length; i++)
{
threads[startOrders[i]].Start();
}
Console.ReadLine();
}
static void ThreadProc()
{
// simulates there are 10 tasks needs to do.
for (int i = 0; i < 10; i++)
{
lock (_sharedBetweenThreads.SyncRoot)
{
Debug.Print(string.Format("Thread #{0} acquired the lock and is working for task #{1}", Thread.CurrentThread.ManagedThreadId, i));
// simulates a work.
Thread.Sleep(500);
}
}
}
}
}
调试输出的屏幕截图
---其他Infos ---
- 该程序根本不是一个并行程序,因为在10个线程之间共享了锁。
- 如果循环的计数从10更改为无限,则始终激活3个线程,其余的7个线程无法获得激活的机会,它们是永远的"僵局"。
我想您的困惑源于您正在使用.NET线程池的事实 - 例如托管线程池 - 但是您希望在系统级别上处理线程,这并不完全相同。内部线程池为您决定合适的线程。这与这个问题无关,哪个核心在哪个时刻运行哪个线程。
使用线程并不意味着您正在使用4个内核。
您必须并行使用:
class Program
{
private static object _lock = new Object();
static void Main(string[] args)
{
Random random = new Random(DateTime.Now.Second);
int[] startOrders = new int[10];
for (int i = 0; i < startOrders.Length; i++)
{
startOrders[i] = i;
}
//shuffle the array
for (int i = startOrders.Length - 1; i >= 0; i--)
{
int j = random.Next(0, i);
int temp = startOrders[i];
startOrders[i] = startOrders[j];
startOrders[j] = temp;
}
Thread[] threads = new Thread[startOrders.Length];
for (int i = 0; i < startOrders.Length; i++)
{
threads[i] = new Thread(ThreadProc)
{
Name = $"#{startOrders[i]}"
};
}
Parallel.ForEach(threads, thread => thread.Start());
Console.ReadLine();
}
static void ThreadProc()
{
// simulates there are 10 tasks needs to do.
for (int i = 0; i < 10; i++)
{
lock (_lock)
{
Debug.Print(
$"Thread {Thread.CurrentThread.Name} acquired the lock and is working for task #{i}");
// simulates a work.
Thread.Sleep(5);
}
}
}
}
输出
Thread #6 acquired the lock and is working for task #0
Thread #4 acquired the lock and is working for task #0
Thread #8 acquired the lock and is working for task #0
Thread #6 acquired the lock and is working for task #1
Thread #5 acquired the lock and is working for task #0
Thread #3 acquired the lock and is working for task #0
Thread #6 acquired the lock and is working for task #2
Thread #7 acquired the lock and is working for task #0
Thread #9 acquired the lock and is working for task #0
Thread #6 acquired the lock and is working for task #3
Thread #4 acquired the lock and is working for task #1
Thread #8 acquired the lock and is working for task #1
Thread #0 acquired the lock and is working for task #0
Thread #5 acquired the lock and is working for task #1
Thread #3 acquired the lock and is working for task #1
Thread #7 acquired the lock and is working for task #1
Thread #9 acquired the lock and is working for task #1
Thread #2 acquired the lock and is working for task #0
Thread #1 acquired the lock and is working for task #0
Thread #0 acquired the lock and is working for task #1
Thread #6 acquired the lock and is working for task #4
Thread #4 acquired the lock and is working for task #2
Thread #8 acquired the lock and is working for task #2
Thread #3 acquired the lock and is working for task #2
Thread #7 acquired the lock and is working for task #2
Thread #5 acquired the lock and is working for task #2
Thread #9 acquired the lock and is working for task #2
Thread #2 acquired the lock and is working for task #1
Thread #0 acquired the lock and is working for task #2
Thread #1 acquired the lock and is working for task #1
Thread #6 acquired the lock and is working for task #5
Thread #4 acquired the lock and is working for task #3
Thread #8 acquired the lock and is working for task #3
Thread #5 acquired the lock and is working for task #3
Thread #3 acquired the lock and is working for task #3
Thread #7 acquired the lock and is working for task #3
Thread #6 acquired the lock and is working for task #6
Thread #4 acquired the lock and is working for task #4
Thread #8 acquired the lock and is working for task #4
Thread #5 acquired the lock and is working for task #4
Thread #3 acquired the lock and is working for task #4
Thread #7 acquired the lock and is working for task #4
Thread #6 acquired the lock and is working for task #7
Thread #4 acquired the lock and is working for task #5
Thread #8 acquired the lock and is working for task #5
Thread #5 acquired the lock and is working for task #5
Thread #3 acquired the lock and is working for task #5
Thread #7 acquired the lock and is working for task #5
Thread #9 acquired the lock and is working for task #3
Thread #6 acquired the lock and is working for task #8
Thread #4 acquired the lock and is working for task #6
Thread #5 acquired the lock and is working for task #6
Thread #8 acquired the lock and is working for task #6
Thread #4 acquired the lock and is working for task #7
Thread #3 acquired the lock and is working for task #6
Thread #6 acquired the lock and is working for task #9
Thread #7 acquired the lock and is working for task #6
The thread 0xfa0 has exited with code 0 (0x0).
Thread #5 acquired the lock and is working for task #7
Thread #8 acquired the lock and is working for task #7
Thread #9 acquired the lock and is working for task #4
Thread #4 acquired the lock and is working for task #8
Thread #3 acquired the lock and is working for task #7
Thread #0 acquired the lock and is working for task #3
Thread #7 acquired the lock and is working for task #7
Thread #5 acquired the lock and is working for task #8
Thread #8 acquired the lock and is working for task #8
Thread #4 acquired the lock and is working for task #9
Thread #3 acquired the lock and is working for task #8
The thread 0x329c has exited with code 0 (0x0).
Thread #9 acquired the lock and is working for task #5
Thread #7 acquired the lock and is working for task #8
Thread #5 acquired the lock and is working for task #9
The thread 0x3fcc has exited with code 0 (0x0).
Thread #8 acquired the lock and is working for task #9
The thread 0xe2c has exited with code 0 (0x0).
Thread #0 acquired the lock and is working for task #4
Thread #3 acquired the lock and is working for task #9
The thread 0x22ec has exited with code 0 (0x0).
Thread #2 acquired the lock and is working for task #2
Thread #7 acquired the lock and is working for task #9
The thread 0x2bfc has exited with code 0 (0x0).
Thread #9 acquired the lock and is working for task #6
Thread #1 acquired the lock and is working for task #2
Thread #0 acquired the lock and is working for task #5
Thread #2 acquired the lock and is working for task #3
Thread #2 acquired the lock and is working for task #4
Thread #9 acquired the lock and is working for task #7
Thread #2 acquired the lock and is working for task #5
Thread #1 acquired the lock and is working for task #3
Thread #0 acquired the lock and is working for task #6
Thread #0 acquired the lock and is working for task #7
Thread #9 acquired the lock and is working for task #8
Thread #2 acquired the lock and is working for task #6
Thread #1 acquired the lock and is working for task #4
Thread #1 acquired the lock and is working for task #5
Thread #0 acquired the lock and is working for task #8
Thread #9 acquired the lock and is working for task #9
The thread 0x1f44 has exited with code 0 (0x0).
Thread #1 acquired the lock and is working for task #6
Thread #2 acquired the lock and is working for task #7
Thread #2 acquired the lock and is working for task #8
Thread #0 acquired the lock and is working for task #9
The thread 0x1fc8 has exited with code 0 (0x0).
Thread #1 acquired the lock and is working for task #7
Thread #1 acquired the lock and is working for task #8
Thread #1 acquired the lock and is working for task #9
The thread 0x2ab0 has exited with code 0 (0x0).
Thread #2 acquired the lock and is working for task #9
The thread 0x2944 has exited with code 0 (0x0).
The thread 0x322c has exited with code 0 (0x0).
The thread 0x146c has exited with code 0 (0x0).
The thread 0x3dcc has exited with code 0 (0x0).
The thread 0x3928 has exited with code 0 (0x0).
我不确定,但是如果我使用thread.name,则thread.currentthread.managedthreadid似乎可以根据需要工作。可以是在线程启动时分配托管threadID,因此#12是执行中的最后一个是有意义的,因为它实际上是最后一个。