Reputation:
I created a simple .NET console application and within it I start 3 managed threads. Each thread executes the following loop:
while (true)
{
System.Console.WriteLine(thread.Name + " " + DateTime.Now);
Thread.Sleep(10);
}
I set the first thread's priority to high and let the app run for several minutes. Overall I expected the first thread to write more frequently to the console. In fact, it had no noticeable effect. Setting the priority to high for one thread seemed the same as leaving all three set to normal.
What about thread priorities am I missing here that would explain this?
Upvotes: 1
Views: 2412
Reputation: 7537
Inspired from @Karim Agha's answer here
I believe this is because of multi-cores CPU
With a simple program to prove this, set both threads run on 1st CPU core:
process.ProcessorAffinity = (IntPtr) 0x0001;
// 0x0001 = 0000 0001 - run on 1st core
// 0x0002 = 0000 0010 - run on 2nd core
// 0x0003 = 0000 0011 - run on 1st and 2nd core
// 0x0004 = 0000 0100 - run on 3rd core
// and so on
And, I'll get something like this highCount:5179 & lowCount:167
after running for a while. If I comment the line, it will be something like this highCount:3350 & lowCount:3382
.
Further evidence will be from Task Manager
, open it and play with Set affinity
settings, and you will see immediate effects applied on both thread.
using System;
using System.Diagnostics;
using System.Threading;
namespace Test
{
class Program
{
private static int highCount, lowCount;
private static readonly ManualResetEventSlim Signal = new ManualResetEventSlim(false);
public static void Main()
{
using (var process = Process.GetCurrentProcess())
{
process.PriorityClass = ProcessPriorityClass.High;
// only run on core number 1
process.ProcessorAffinity = (IntPtr) 0x0001;
}
var slowThread = new Thread(() =>
{
while (true)
{
if (Signal.IsSet)
{
break;
}
Console.WriteLine("Lowest");
lowCount++;
}
})
{
Name = "Lowest",
Priority = ThreadPriority.Lowest
};
var fastThread = new Thread(() =>
{
while (true)
{
if (Signal.IsSet)
{
break;
}
Console.WriteLine("Highest");
highCount++;
}
})
{
Name = "Highest",
Priority = ThreadPriority.Highest
};
fastThread.Start();
slowThread.Start();
Console.ReadKey();
Signal.Set();
fastThread.Join();
slowThread.Join();
Console.WriteLine($"highCount:{highCount} & lowCount:{lowCount}");
Console.ReadKey();
}
}
}
Upvotes: 1
Reputation: 3625
You are not seeing any difference because you are probably running this program on a multi-processor machine, where the threads do not have to compete against each other to be scheduled on a single core.
When the high-priority thread is executing, the scheduler could still schedule the low-priority thread to the other cores, thus you are not seeing any significant difference.
If you want to notice a significant difference, you have to force the threads to compete for a time-slice against a single core, where only one thread at a time could execute. To achieve this, you should set the processor affinity for all the threads to a the same single core.
I'm not sure how you can do this in .NET, but in C you should use the SetThreadAffinityMask
function:
HANDLE hThreadLow = CreateThread(NULL, 0, ThreadProc1,
NULL, CREATE_SUSPENDED, &dwThreadLowId);
HANDLE hThreadHigh = CreateThread(NULL, 0, ThreadProc2,
NULL, CREATE_SUSPENDED, &dwThreadHighId);
SetThreadPriority(hThreadLow, THREAD_PRIORITY_BELOW_NORMAL);
SetThreadPriority(hThreadHigh, THREAD_PRIORITY_ABOVE_NORMAL);
SetThreadAffinityMask(hThreadHigh, 0x00000001);
SetThreadAffinityMask(hThreadLow, 0x00000001);
ResumeThread(hThreadLow);
ResumeThread(hThreadHigh);
Now you'll notice a significant difference between the two threads. Implement a counter in each of the two threads and see the differences ranging from 100x - 10000x in the counted values.
Upvotes: 2
Reputation: 3427
Try Sleep(1)
instead. 10ms is eternity in thread time, however Sleep(1)
basically says "I yield the rest of my time slice for execution to another thread" which I think is what you want. Thread priority doesn't just make a thread execute more often, it just says "if the scheduler has a choice between giving thread A a timeslice and thread B a timeslice, give it to the one with the higher priority." Try this change and see what happens. Alternately, make each thread take a different amount of time to execute (don't use sleep for this though, print 100 elements in a loop on one, print 1000 on another, etc.)
Edit: changed to Sleep(1), not sure why it was modified. See my comment below for why Sleep(1) is a better choice here.
Upvotes: 7
Reputation: 8502
ThreadPriority may not behave as expected... some reading material on thread priority...
Thread Priorities are Evil
http://www.codinghorror.com/blog/archives/000671.html
ThreadPriority.BelowNormal
http://odetocode.com/Blogs/scott/archive/2006/08/27/6053.aspx
Why Sleep(1) is better than Sleep(0)
http://www.bluebytesoftware.com/blog/PermaLink,guid,1c013d42-c983-4102-9233-ca54b8f3d1a1.aspx
Upvotes: 1
Reputation: 6208
If printing by all three threads takes less than 10ms then you won't see any effect on output. Try to come up with a task that takes a long time say calculate square roots up to a million then see who runs more often.
Upvotes: 3
Reputation: 158309
If you lose the Thread.Sleep
statements you are likely to see more action from the higher-priority thread. Thread.Sleep
gives the other thread(s) plenty of time to do their thing.
Upvotes: 1
Reputation: 33914
The threads won't write more frequently to the console because they're all waiting 10ms between writes. However, the high-priority thread should write to the console more regularly, i.e. closer to true 10ms between writes. This is because, while the lower-priority threads can get pushed aside by other tasks on the PC, the higher-priority thread will have to wait less before being allowed to write.
Does that answer your question?
Upvotes: 0