I am exploring threading concept,
Every time when i tried to execute the below code, I am getting different output.
I am starting ThreadOne first, But why is ThreadTwo getting started.
Why am I getting Different output? Can someone explain in Detail?
Thanks In Advance.
static Object newLockobj = new Object();
static void Main(string[] args)
{
Thread tobj1 = new Thread(ThreadOne);
Thread tobj2 = new Thread(ThreadTwo);
tobj1.Start();
tobj2.Start();
Console.ReadLine();
}
static void ThreadOne()
{
Console.WriteLine("Thread One Entered");
lock (newLockobj)
{
Console.WriteLine("Thread 1 started");
Thread.Sleep(2000);
Console.WriteLine("Thread 1 ended");
}
}
static void ThreadTwo()
{
Console.WriteLine("Thread Two Entered");
lock (newLockobj)
{
Console.WriteLine("Thread 2 started");
Thread.Sleep(1000);
Console.WriteLine("Thread 2 ended");
}
}
This is a basic examle for Concurrency. Once you call the .Start() method on a thread object, it starts getting executed independent of the thread that started it. What your programm is doing:
Create the thread objects
Start tobj1 (the thread is not executed directly, but once the scheduler finds a place to put it)
Start tobj2 (the thread is again not executed directly)
The scheduler is responsible to tell the processor which process and which thread to execute. The order in which the threads are started is of no importance.
As soon as one thread starts, he prints the first line ("Thread X Entered"). The Lock is a synchronization statement. Since both threads sync on the same object instance, they cannot enter the Lock block both (Mutual Exclusion). The Lock statement only ensures that the process can work in the critical section without the other process working it his critical section. As you see in your right output, a thread can be interrupted although he is in his critical section ("Thread 2 started", "Thread One Entered", "..."). "Thread One", however, is not allowed to his critical section since the other thread did not release the lock yet.
This is in the heart of threads programming. While you have control over which thread you want to start first, the CPU is not obliged to follow your order of events. During the execution of one thread the CPU is guaranteed to follow you order of code execution as per your programming. When it comes to scheduling different threads, the CPU will follow its own logic and sometimes that logic can seem like random behavior. It will allocate processing time to different threads as it sees fit.
I suggest you read up more on threads programming as not fully understanding this concept and appreciating it's potential pitfalls will lead to many days of hair pulling and possible deadlocks :)
Just google: c# threading. You will get plenty of good resources!
Related
I am creating an app that deals with huge number of data to be processed. I want to use threading in C# just to make it processes faster. Please see example code below.
private static void MyProcess(Object someData)
{
//Do some data processing
}
static void Main(string[] args)
{
for (int task = 1; task < 10; task++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(MyProcess), task);
}
}
Does this mean that a new thread will be created every loop passing the task to the "MyProcess" method (10 threads total)? Also, are the threads going to process concurrently?
The number of threads a threadpool will start depends on multiple factors, see The managed thread pool
Basically you are queing 10 worker items here which are likely to start threads immediatly.
The threads will most likly run concurrently, depending on the machine and number of processors.
If you start a large number of worker items, they will end up in a queue and start running as soon as a thread becomes available.
The calls will be scheduled on the thread pool. It does not guarantee that 10 threads will be created nor that all 10 tasks will be executed concurrently. The number of threads in the thread pool depends on the hardware and is chosen automatically to provide the best performance.
This articles contain good explanations of how it works:
https://owlcation.com/stem/C-ThreadPool-and-its-Task-Queue-Example
https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadpool?redirectedfrom=MSDN&view=netframework-4.8
https://www.c-sharpcorner.com/article/thread-pool-in-net-core-and-c-sharp/
This Stackoverflow question explains the difference between ThreadPool and Thread:
Thread vs ThreadPool
Your method will be queued 9 times (you start at 1, not 0) for execution and will be executed when a thredpool thread will be available.
Just for fun, I wrote this code to simulate a deadlock. Then, I sat and watched it run patiently until the total number of available worker threads that the thread pool had went down to zero. I was curious to see what would happen. Would it throw an exception?
using System;
using System.Diagnostics;
using System.Threading;
namespace Deadlock
{
class Program
{
private static readonly object lockA = new object();
private static readonly object lockB = new object();
static void Main(string[] args)
{
int worker, io;
ThreadPool.GetAvailableThreads(out worker, out io);
Console.WriteLine($"Total number of thread pool threads: {worker}, {io}");
Console.WriteLine($"Total threads in my process: {Process.GetCurrentProcess().Threads.Count}");
Console.ReadKey();
try
{
for (int i = 0; i < 1000000; i++)
{
AutoResetEvent auto1 = new AutoResetEvent(false);
AutoResetEvent auto2 = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(ThreadProc1, auto1);
ThreadPool.QueueUserWorkItem(ThreadProc2, auto2);
var allCompleted = WaitHandle.WaitAll(new[] { auto1, auto2 }, 20);
ThreadPool.GetAvailableThreads(out worker, out io);
var total = Process.GetCurrentProcess().Threads.Count;
if (allCompleted)
{
Console.WriteLine($"All threads done: (Iteration #{i + 1}). Total: {total}, Available: {worker}, {io}\n");
}
else
{
Console.WriteLine($"Timed out: (Iteration #{i + 1}). Total: {total}, Available: {worker}, {io}\n");
}
}
Console.WriteLine("Press any key to exit...");
}
catch(Exception ex)
{
Console.WriteLine("An exception occurred.");
Console.WriteLine($"{ex.GetType().Name}: {ex.Message}");
Console.WriteLine("The program will now exit. Press any key to terminate the program...");
}
Console.ReadKey();
}
static void ThreadProc1(object state)
{
lock(lockA)
{
Console.WriteLine("ThreadProc1 entered lockA. Going to acquire lockB");
lock(lockB)
{
Console.WriteLine("ThreadProc1 acquired both locks: lockA and lockB.");
//Do stuff
Console.WriteLine("ThreadProc1 running...");
}
}
if (state != null)
{
((AutoResetEvent)state).Set();
}
}
static void ThreadProc2(object state)
{
lock(lockB)
{
Console.WriteLine("ThreadProc2 entered lockB. Going to acquire lockA.");
lock(lockA)
{
Console.WriteLine("ThreadProc2 acquired both locks: lockA and lockB.");
// Do stuff
Console.WriteLine("ThreadProc2 running...");
}
}
if (state != null)
{
((AutoResetEvent)state).Set();
}
}
}
}
Meanwhile, I also kept the Windows Task Manager's Performance tab running and watched the total number of operating system threads go up as my program ate up more threads.
Here is what I observed:
The OS didn't create more threads as the .NET thread pool created a thread every time. In fact, for every four or five iterations that my for loop ran, the OS thread-count would go up by one or two. This was interesting, but this isn't my question. It proves what has already been established.
More interestingly, I observed that the number of threads did not decrease by 2 on every iteration of my for loop. I expected that it should have gone down by 2 because none of my deadlocked threads are expected to return since they are deadlocked, waiting on each other.
I also observed that when the total number of available worker threads in the thread pool went down to zero, the program still kept running more iterations of my for-loop. This made me curious as to where those new threads were coming from if the thread pool had already run out of threads and none of the threads had returned?
So, to clarify, my two question(s), which, perhaps are related in that a single answer may be the explanation to them, are:
When a single iteration of my for-loop ran, for some of those iterations, no thread pool threads were created. Why? And where did the thread pool get the threads to run these iterations on?
Where did the thread pool get the threads from when it ran out of its total number of available worker threads and still kept running my for loop?
ThreadPool.GetAvailableThreads(out worker, out io);
That's not a great statistic to show you how the thread pool works. Primary problem is that it is ridiculously large number on all recent .NET versions. On my dual-core laptop, it starts out at 1020 in 32-bit mode, 32767 in 64-bit mode. Far, far larger than such an anemic CPU could reasonably handle. This number has significantly inflated over the years, it started out at 50x the number of cores back in .NET 2.0. It is now dynamically calculated based on machine capabilities, the job of the CLR host. It uses a glass that's well over half-full.
The primary job of the threadpool manager is to keep threading efficient. The sweet-spot is to keep the number of executing threads limited to the number of processor cores. Running more reduces perf, the OS then has to context-switch between threads and that adds overhead.
That ideal however cannot always be met, practical tp threads that programmers write are not always well-behaved. In practice they take too long and/or spend too much time blocking on I/O or a lock instead of executing code. Where your example is of course a rather extreme case of blocking.
The thread pool manager is not otherwise aware of exactly why a tp thread takes too long to execute. All it can see is that it takes too long to complete. Getting deep insight into exactly why a thread takes too long is not practical, it takes a debugger and the kind heavily trained massively parallel neural network that programmers have between their ears.
Twice a second, the thread pool manager re-evaluates the work load and allows an extra tp thread to start when none of the active ones complete. Even though that is beyond the optimum. On the theory that this is likely to get more work done since presumably the active ones are blocking too much and not using the available cores efficiently. Also important to solve some deadlock scenarios, albeit that you never want to need that. It is just a regular thread like any other, underlying OS call is CreateThread().
So that's what you see, the number of available threads drops by one twice a second. Independent of your code, this is time-based. There is actually a feedback loop implemented in the manager that tries to dynamically calculate the optimum number of extra threads. You never got there yet with all threads blocking.
This does not go on forever, you ultimately reach the high upper limit set by the default SetMaxThreads(). No exception, assuming you did not hit an OutOfMemoryException first and you'd commonly experience in real life, it just stops adding more threads. You are still adding execution requests to the thread pool, covers bullet 3, they just never actually get started. Eventually you'll run out of memory when the number of requests get too large. You'll have to wait for a long time, takes a while to fill up a gigabyte.
The cause is QueueUserWorkItem: "Queues a method for execution. The method executes when a thread pool thread becomes available." https://msdn.microsoft.com/en-us/library/kbf0f1ct(v=vs.110).aspx
In my understanding Threadpool just slowly increases the number of threads to fit your demand, this is what you see in taskmgr. i think you could verify this by adding some things to be done to your thread.
edit: What I mean is, you just queue them, the first threads are starting, and slowly slowly (every 500ms, https://blogs.msdn.microsoft.com/pedram/2007/08/05/dedicated-thread-or-a-threadpool-thread/) more and more threads are added until limits are reached - afterwards you can still queue new ones.
The thread pool (almost) never runs out of threads. There's an injection heuristic that adds new threads in an (almost) unbounded way when it thinks this is helping throughput. This also is a guard against deadlocks based on too few threads being available.
This can be a big problem because memory usage is (almost) unbounded.
"Almost" because there is a maximum thread count but that tends to be extremely high in practice (thousands of threads).
When a single iteration of my for-loop ran, for some of those iterations, no thread pool threads were created.
The reason is not apparent to me from the data shown. You probably should measure Process.GetCurrentProcess().ThreadCount after each iteration.
Maybe the deadlock was avoided in some cases? It's not a deterministic deadlock.
On the current CLR running threads appear to be 1:1 with OS threads.
Maybe you should run a simpler benchmark?
for (int i = 0; i < 10000000; i++)
{
Task.Run(() => Thread.Sleep(Timeout.Infinite));
int workerThreads;
int cpThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out cpThreads);
Console.WriteLine($"Queued: {i}, threads: {Process.GetCurrentProcess().Threads.Count}, workerThreads: {workerThreads}, workerThreads: {cpThreads}");
Thread.Sleep(100);
}
I have a code which synchronize threads via AutoResetEvent
Basically there are two threads which swap control and execute commands , each thread at a time.
Code :
static EventWaitHandle _waitHandle = new AutoResetEvent(false);
static void Waiter()
{
_waitHandle.WaitOne();
Console.WriteLine("A...");
_waitHandle.Set();
_waitHandle.WaitOne();
Console.WriteLine("A2...");
_waitHandle.Set();
}
static void Waiter2()
{
_waitHandle.WaitOne();
Console.WriteLine("B...");
_waitHandle.Set();
_waitHandle.WaitOne();
Console.WriteLine("B2...");
}
void Main()
{
new Thread(Waiter).Start();
new Thread(Waiter2).Start();
_waitHandle.Set(); // Wake up the Waiter.
}
Result : (I always get this result)
A...
B...
A2...
B2...
However - when I move to Tasks :
Task.Run(()=>Waiter());
Task.Run(()=>Waiter2());
I sometimes get :
B...
A...
B2...
Which is clear to me because the task scheduler scheduled the second task to execute first.
Which leads me to ask :
Questions
1) Do threads order guaranteed to be the same as order of invocation in :
new Thread(Waiter).Start();
new Thread(Waiter2).Start();
//In other words , will I always get the first result ?
2) How can I Force the Task.Runs to be invoked the same order as I invoke them?
No, it is not guaranteed, you just got lucky that the output was the same every time.
Add in a 2nd AutoResetEvent that has a WaitOne between the two tasks and a Set in at the start of the Waiter method.
Without a synchronization mechanism, you cannot guarantee the order in which a thread will start and/or execute. Furthermore, a thread's execution may be preempted (think: "paused") at any time.
So to answer your questions:
No
No
Before moving forward, you should ask yourself "Do I really need to use threads to solve this problem?"
My favorite quote from the Microsoft's MSDN:
"When you use multithreading of any sort, you potentially expose yourself to very serious and complex bugs" [Best Practices for Implementing the Event-based Asynchronous Pattern]
If you do need to introduce threads, then I would begin by familiarizing yourself with some of Microsoft's synchronization mechanisms:
Critical Section
Mutex
Events
Auto Reset
Manual Reset
I wrote this little program:
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(WriteX);
t.Start();
for (int i = 0; i < 1000; i++)
{
Console.Write("O");
}
}
private static void WriteX()
{
for (int i = 0; i < 1000; i++)
{
Console.Write(".");
}
}
}
I ran it about fifty times, and the first character on the console was always "O". It is weird for me, because the t thread starts first then the main continues.
Is there any explanation for this?
This is probably because Thread.Start first causes the change of state of thread on which it is called and OS schedules it for execution whereas the main thread is already running and does not need these two steps. This is probably the reason that the statement in main thread executes first rather the one in the newly created thread. Keep in mind the sequence of thread execution is not guaranteed.
Thread.Start Method
1) Thread.Start Method Causes the operating system to change the state of
the current instance to ThreadState.Running.
2) Once a thread is in the ThreadState.Running state, the operating
system can schedule it for execution. The thread begins executing at
the first line of the method represented by the ThreadStart
Edit It seems to me that representing this in graphical form will make this more clear and understandable. I tried to show the sequence of thread execution in diagram below.
You say:
"It is weird for me, because the t thread starts first then the main continues.".
This is not true. The "main" tread is already running. When t.Start(); is executed, the OS is told t is in the running state. The OS will then schedule execution time for the thread "soon". This is something else than the OS is instructed to stop execution of this thread until thread t is started. In other words, when Start returns, there is no guarantee that the thread has already started executing.
More of an advice than not an answer:
(Please note, that I see no real-life use for what you are trying to achieve, so I treat your problem as a thought experiment/proof of a concept not explained in detail.)
If you want your threads to "race" for control, don't give your main thread a head start! Creating a thread has some overhead and your main thread is already created (since it creates your other thread). If you are looking for a mostly equal chance for both of your main and worker thread, you should wait for your worker thread to be created in the main thread and wait for the main thread to start the race in your background thread. This can be achived by synch objects.
In practice it would look like this:
You should declare two ManualResetEvents which are visible for both your main- and background thread like this:
private static ManualResetEvent backgroundThreadReady = new ManualResetEvent(false);
private static ManualResetEvent startThreadRace = new ManualResetEvent(false);
Then in your main thread, you should wait for your thread being initialized like:
static void Main(string[] args)
{
Thread t = new Thread(WriteX);
t.Start();
backgroundThreadReady.WaitOne(); // wait for background thread to be ready
startThreadRace.Set(); // signal your background thread to start the race
for (int i = 0; i < 1000; i++)
{
Console.Write("O");
}
}
And in your thread:
private static void WriteX()
{
backgroundThreadReady.Set(); // inform your main thread that this thread is ready for the race
startThreadRace.WaitOne(); // wait 'till the main thread starts the race
for (int i = 0; i < 1000; i++)
{
Console.Write(".");
}
}
Please note that I could have used other waitable sync objects (mutex, autoreset event, even a critical section lock with some hack, I've just choose the simplest, fastest solution which can be extended easily).
Your code is non deterministic. Your code contains no thread primitives that would schedule priority of one thread over another or for one thread to wait for another.
Main process continue its next instructions set after invoking the thread ,It will take time to start thread method as light process.
It basically needs time to start the thread up. You are running the thread code at the same time as the rest of the first method. So taking into account the time it takes to start the thread and then get to the point where it is writing the "." does that make sense?
If you have a sort of reset button in your app to start everything again (without exiting) you may find that the first character is the "." because the thread will already exist.
There is only one reason why the main thread will finish before the created thread and that is because it takes time to start a thread. The only time you would use threads to speed up a program is when 2 tasks can be run at the exact same time. If you want to make the second loop finish first , take a look at Parallel.For loops in c#... these will run each loop in the for loop at the same time (not all of them but as much as your PC can handle)
I have the following code:
static void Main(string[] args)
{
Console.Write("Press ENTER to start...");
Console.ReadLine();
Console.WriteLine("Scheduling work...");
for (int i = 0; i < 1000; i++)
{
//ThreadPool.QueueUserWorkItem(_ =>
new Thread(_ =>
{
Thread.Sleep(1000);
}).Start();
}
Console.ReadLine();
}
According to the textbook C# 4.0 Unleashed by Bart De Smet (page 1466), using new Thread should mean using many more threads than if you use ThreadPool.QueueUserWorkItem which is commented out in my code.
However I've tried both, and seen in Resource Monitor that with "new Thread", there are about 11 threads allocated, however when I use ThreadPool.QueueUserWorkItem, there are about 50.
Why am I getting the opposite outcome of what is mentioned in this book?
Also why if you increase the sleep time, do you get many more threads allocated when using ThreadPool.QueueUserWorkItem?
new Thread() just creates a Thread object; you forgot to call Start() (which creates the actual thread that you see in resource monitor).
Also, if you are looking at the number of threads after the sleep has completed, you won't see any of the new Threads as they have already exited.
On the other hand, the ThreadPool keeps threads around for some time so it can reuse them, so in that case you can still see the threads even after the sleep has completed.
With new Thread(), you might be seeing the number staying around 160 because it took one second to start that many threads, so by the time the 161st thread is started, the first thread is already finished. You should see a higher number of threads if you increase the sleep time.
As for the ThreadPool, it is designed to use as few threads as possible while also keeping the CPU busy. Ideally, the number of busy threads is equal to the number of CPU cores. However, if the pool detects that its threads are currently not using the CPU (sleeping, or waiting for another thread), it starts up more threads (at a rate of 1/second, up to some maximum) to keep the CPU busy.