Why do I repeatedly get the same result with this unsynchronized code? - c#

Consider this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Multithreading
{
class Program
{
static int result = 0;
static void changeResult1()
{
result = 1;
}
static void changeResult2()
{
result = 2;
}
static void changeResult3()
{
result = 3;
}
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(changeResult1));
Thread t2 = new Thread(new ThreadStart(changeResult2));
Thread t3 = new Thread(new ThreadStart(changeResult3));
t1.Start();
t2.Start();
t3.Start();
Console.WriteLine(result);
}
}
}
I'm pretty sure that this code is NOT synchronized , meaning that result should be different each execution of the code (0,1,2,3) . From my point of view the result can even be 0 , if the Main thread is done before either one of the thread had even started .
However I'm repeatedly getting 2 as the result on screen .
Why ?

Is this code correctly synchronized ?
No.
meaning that result should be different each execution of the code (0,1,2,3) .
Why should that be true? You provide no justification whatsoever for this claim.
The code is incorrectly synchronized which means that there are many possible results. You are taking a fact -- the lack of correct synchronization means I don't know what will happen -- and deducing from that a completely unsupported conclusion -- the observations will be different on every execution. The correct deduction from "I don't know what will happen" is that you don't know what will happen on any execution; in particular you do not know that the behaviour over a large set of runs will have any particular distribution.
Why ?
Why what? You noted that 2 was a possible result, you are getting a possible result. You do the same thing twice and the same result happens; that's not surprising. Just because the runtime is permitted to produce many different results does not imply that it must produce many different results. Doing the same thing twice generally results in pretty similar outcomes.

It seems to me that the observed outcome is quite reasonable.
Starting threads is an expensive operation. I would expect that the start-up time of each of the threads to vastly outweigh the time taken to actually run the code assigned to each thread.
So once thread 1 is set-up, the main thread moves on to setting up thread 2 while thread 1 executes. Thread 1 finishes long before thread 2 is ready to run.
The same with thread 2 & thread 3.
So once thread three is set-up, thread 2 has well-and-truly finished, and the main thread moves immediately to the Console.WriteLine(result);. This is before thread 3 actually has begun, and is a long, long, long time after thread 2 has completed.
So, of course, the results is almost always 2.
To support my unscientific analysis I thought I might add some timing code to see if I could be right.
void Main()
{
times[0] = sw.Elapsed.TotalMilliseconds;
Thread t1 = new Thread(new ThreadStart(changeResult1));
times[1] = sw.Elapsed.TotalMilliseconds;
Thread t2 = new Thread(new ThreadStart(changeResult2));
times[2] = sw.Elapsed.TotalMilliseconds;
Thread t3 = new Thread(new ThreadStart(changeResult3));
times[3] = sw.Elapsed.TotalMilliseconds;
t1.Start();
times[4] = sw.Elapsed.TotalMilliseconds;
t2.Start();
times[5] = sw.Elapsed.TotalMilliseconds;
t3.Start();
times[6] = sw.Elapsed.TotalMilliseconds;
var r = result.ToString();
times[7] = sw.Elapsed.TotalMilliseconds;
Console.WriteLine(result);
times[8] = sw.Elapsed.TotalMilliseconds;
Thread.Sleep(1000);
times
.Select((x, n) => new { t = (x - times[0]).ToString("0.000"), n})
.OrderBy(x => x.t)
.Dump();
}
static Stopwatch sw = Stopwatch.StartNew();
static double[] times = new double[15];
static int result = 0;
static void changeResult1()
{
times[9] = sw.Elapsed.TotalMilliseconds;
result = 1;
times[10] = sw.Elapsed.TotalMilliseconds;
}
static void changeResult2()
{
times[11] = sw.Elapsed.TotalMilliseconds;
result = 2;
times[12] = sw.Elapsed.TotalMilliseconds;
}
static void changeResult3()
{
times[13] = sw.Elapsed.TotalMilliseconds;
result = 3;
times[14] = sw.Elapsed.TotalMilliseconds;
}
You have to follow the bouncing ball a little, but one such run of this code produced this output:
This is quite clearly showing that the code that executes after t3.Start(); is the var r = result.ToString(); and not the result = 3;. More importantly result = 2; has happened a long time before thread 3 has started.

Related

Join statement in multiple thread

I have a program that starts 2 threads and use Join.My understanding says that joins blocks the calling operation till it is finished executing .So,the below program should give 2 Million as answer since both the threads blocks till execution is completed but I am always getting the different value.This might be because first thread is completed but second thread is not run completely.
Can someone please explain the output.
Reference -Multithreading: When would I use a Join?
namespace ThreadSample
{
class Program
{
static int Total = 0;
public static void Main()
{
Thread thread1 = new Thread(Program.AddOneMillion);
Thread thread2 = new Thread(Program.AddOneMillion);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine("Total = " + Total);
Console.ReadLine();
}
public static void AddOneMillion()
{
for (int i = 1; i <= 1000000; i++)
{
Total++;
}
}
}
}
When you call start method of thread, it starts immediately. hence by the time u call join on the thread1, thread2 would also have started. As a result variable 'Total' will be accessed by both threads simultaneously. Hence you will not get correct result as one thread operation is overwriting the value of 'Total' value causing data lose.
public static void Main()
{
Thread thread1 = new Thread(Program.AddOneMillion);
Thread thread2 = new Thread(Program.AddOneMillion);
thread1.Start(); //starts immediately
thread2.Start();//starts immediately
thread1.Join(); //By the time this line executes, both threads have accessed the Total varaible causing data loss or corruption.
thread2.Join();
Console.WriteLine("Total = " + Total);
Console.ReadLine();
}
Inorder to correct results either u can lock the Total variable as follows
static object _l = new object();
public static void AddOneMillion()
{
for (int i = 0; i < 1000000; i++)
{
lock(_l)
ii++;
}
}
U can use Interlocked.Increment which atomically updates the variable.
Please refer the link posted by #Emanuel Vintilă in the comment for more insight.
public static void AddOneMillion()
{
for (int i = 0; i < 1000000; i++)
{
Interlocked.Increment(ref Total);
}
}
It's because the increment operation is not done atomically. That means that each thread may hold a copy of Total and increment it. To avoid that you can use a lock or Interlock.Increment that is specific to incrementing a variable.
Clarification:
thread 1: read copy of Total
thread 2: read copy of Total
thread 1: increment and store Total
thread 2: increment and store Total (overwriting previous value)
I leave you with all possible scenarios where things could go wrong.
I would suggest avoiding explicit threading when possible and use map reduce operations that are less error prone.
You need to read about multi-threading programming and functional programming constructs available in mainstream languages. Most languages have added libraries to leverage the multicore capabilities of modern CPUs.

Multithreading and change Priority

I create 3 Threads in main with 3 different method.
Thread t1 = new Thread(FirstThread);
Thread t2 = new Thread(SecondThread);
Thread t3 = new Thread(ThirdThread);
I need measured time on every thread and search less of them.
The time is measured with Stopwatch. I didn't find another way(in c/c++ i know method GetThreadTimes).
static void FirstThread()
{
Stopwatch stopwatch = Stopwatch.StartNew();
try
{
Enumerable.Range(1, 10000).Select(x => x).Sum();
}
finally
{
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
}
}
After (on task) Dynamic change Thread's priority and again start method example:
thr2.priority = ThreadPriority.Highest;
I don't understand as i could begun threads with changed priority if this is IMPOSSIBLE, because thread start 1 time.
Out on display time with normal and low priority all threads.
p.s. I think that Stopwatch compared variable cast to double or I don't see any other way...
double timeInSecondsPerN = Stopwatch1.Elapsed.TotalMilliseconds
The main question to look the work of threads with different priorities in the program runtime
Thread priority will not necessarily make a task faster or accomplish 'more work'
If you set 3 threads to all be priority highest - then they will all be competing for CPU cycles at the same speed/rate, probably the same speed as if they were all thread priority BelowNormal.
All it means is that if your application gets to the point of being deadlocked and competing for CPU Cycles, it knows which thread to satisfy first.
This feature of .Net loses its benefits if you set all threads to the same high value. The feature only has value, if you use the Higher priority settings for threads that genuinely need to be satisfied before all others within your application.
Eg: Important computational tasks with low IO usage. (Encryption, Cryptocurrency, Hashing etc)
If your application is not getting to the point of being thread-locked or utilizing 100% of a cpu core, then the priority feature will never kick in.
The Microsoft website on Thread.Priority demonstrates the effect of priority well.
https://msdn.microsoft.com/en-us/library/system.threading.thread.priority(v=vs.110).aspx
using System;
using System.Threading;
using Timers = System.Timers;
class Test
{
static void Main()
{
PriorityTest priorityTest = new PriorityTest();
Thread thread1 = new Thread(priorityTest.ThreadMethod);
thread1.Name = "ThreadOne";
Thread thread2 = new Thread(priorityTest.ThreadMethod);
thread2.Name = "ThreadTwo";
thread2.Priority = ThreadPriority.BelowNormal;
Thread thread3 = new Thread(priorityTest.ThreadMethod);
thread3.Name = "ThreadThree";
thread3.Priority = ThreadPriority.AboveNormal;
thread1.Start();
thread2.Start();
thread3.Start();
// Allow counting for 10 seconds.
Thread.Sleep(10000);
priorityTest.LoopSwitch = false;
}
}
class PriorityTest
{
static bool loopSwitch;
[ThreadStatic] static long threadCount = 0;
public PriorityTest()
{
loopSwitch = true;
}
public bool LoopSwitch
{
set{ loopSwitch = value; }
}
public void ThreadMethod()
{
while(loopSwitch)
{
threadCount++;
}
Console.WriteLine("{0,-11} with {1,11} priority " +
"has a count = {2,13}", Thread.CurrentThread.Name,
Thread.CurrentThread.Priority.ToString(),
threadCount.ToString("N0"));
}
}
// The example displays output like the following:
// ThreadOne with Normal priority has a count = 755,897,581
// ThreadThree with AboveNormal priority has a count = 778,099,094
// ThreadTwo with BelowNormal priority has a count = 7,840,984

C# Multithreading - Threads don't run

I am teaching myself C# from my usual C++ programming and now I'm doing threads.
The following simple code compiles fine and should output beeps on a loop via threads for 30 seconds.
using System;
using System.Runtime.InteropServices;
using System.Threading;
class BeepSample
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool Beep(uint dwFreq, uint dwDuration);
static void Main()
{
Console.WriteLine("Testing PC speaker...");
for (uint i = 100; i <= 20000; i++)
{
var BeepThread = new Thread(delegate() { Beep(i, 30000); });
}
Console.WriteLine("Testing complete.");
Console.ReadLine();
}
}
Only problem is the threads don't seem to work.
I know I am missing something basic.
Any ideas?
Your forgot to start thread MSDN link
for (uint i = 100; i <= 20000; i++)
{
var BeepThread = new Thread(delegate() { Beep(i, 30000); });
BeepThread.Start();
}
However that looks suspicious. Why would you need 19900 threads? Probably you want to have 1 thread, that has a loop inside and pauses for short periods to output different frequency through beeper.
Only problem is the threads don't seem to work.
This aspect is clear from the part that you have not started the threads for them to do anything
Code has many other issues:
Closure issue, needs further modification as
for (uint i = 100; i <= 20000; i++)
{
int icopy = i;
var BeepThread = new Thread(delegate() { Beep(icopy, 30000); });
BeepThread.Start();
}
Thread class will start the foreground threads and each logical processor core has capacity to process one thread at a time and each Thread is a very costly resource for the computation and memory as it needs allocation of Thread Environment Block, Kernel Stack Memory, User Stack Memory, the current code even if it runs, will kill your system and you mostly have to kill the process to come out of it
Console.ReadLine(); will only block the Main Thread / Ui Thread, others threads being foreground will go on even if Main thread / Ui thread exits and not blocked, ideal way to block is calling Join on each Thread object, which will ask Main thread to wait till its complete
One of the preferred way to re-write the same code is using the Task Parallel Library:
Parallel.For(100, 20000,
, new ParallelOptions { MaxDegreeOfParallelism =
Environment.ProcessorCount }
i =>
{
int icopy = i;
Beep(icopy, 30000);
});
Benefits:
Code doesn't create so many threads and kill the system
Works on thread pool (Background threads) and use only required number of threads are invoked and max number never exceeds the Processor count of the system and would be mostly far lesser, as threads are reused since there's no major long running computation
Automatically blocks Main thread / Ui Thread
Ok, thanks guys. Had gone for lunch.
I implemented...
for (uint i = 500; i <= 550; i++)
{
uint icopy = i;
var BeepThread = new Thread(delegate() { Beep(icopy, 30000); });
BeepThread.Start();
}
Which worked great.
As predicted the threads did not terminate after the main thread was executed but it does what I want which is awesome.
Bless y'all.

Control threads using AutoResetEvent in C#

Say I have a class A and a class B representing tasks.
I want to perform an experiment, and for the experiment to start I need to finish at least 5 B tasks and only 1 A task.
I have the following classes
abstract class Task
{
public int Id;
public void Start(object resetEvent)
{
EventWaitHandle ewh = (EventWaitHandle)resetEvent;
Thread.Sleep(new Random(DateTime.Now.Ticks.GetHashCode()).Next(5000, 14000));
Console.WriteLine("{0} {1} starts",this.GetType().Name, Id);
ewh.Set();
}
}
class A : Task
{
static int ID = 1;
public A(EventWaitHandle resetEvent)
{
Id = ID++;
new Thread(StartTask).Start(resetEvent);
}
}
class B : Task
{
static int ID = 1;
public B(EventWaitHandle resetEvent)
{
Id = ID++;
new Thread(StartTask).Start(resetEvent);
}
}
and the following main
static void Main()
{
A a;
B[] bs = new B[20];
int numberOfBs = 0;
EventWaitHandle aResetEvent = new AutoResetEvent(false);
EventWaitHandle bResetEvent = new AutoResetEvent(false);
a = new A(aResetEvent);
for (int i = 0; i < bs.Length; i++)
bs[i] = new B(bResetEvent);
while (numberOfBs < 5)
{
bResetEvent.WaitOne();
numberOfBs++;
}
aResetEvent.WaitOne();
Console.WriteLine("Experiment started with {0} B's!", numberOfBs);
Thread.Sleep(3000); // check how many B's got in the middle
Console.WriteLine("Experiment ended with {0} B's!", numberOfBs);
}
now I have few problems/questions:
How can I wait for only N signals out of possible M?
Can I achieve the result I'm looking for with only 1 AutoResetEvent?
I don't understand why all the tasks are printed together, I expected each task to be printed when it is done and now when everything is done.
is the following code thread safe?
.
while (numberOfBs < 5)
{
bResetEvent.WaitOne();
numberOfBs++;
}
could it be that couple of threads signal together? if so, can I fix that using lock on bResetEvent?
1.How can I wait for only N signals out of possible M?
Just as you do here (sort of…see answer to #4).
2.Can I achieve the result I'm looking for with only 1 AutoResetEvent?
Yes. But you will need two counters in that case (one for the A type and one for the B type), and they will need to be accessed in a thread-safe way, e.g. with the Interlocked class, or using a lock statement. All threads, A and B types, will share the same AutoResetEvent, but increment their own type's counter. The main thread can monitor each counter and process once both counters are at their desired value (1 for the A counter, 5 for the B counter).
I'd recommend using the lock statement approach, as it's simpler and would allow you to avoid using AutoResetEvent altogether (the lock statement uses the Monitor class, which provides some functionality similar to AutoResetEvent, while also providing the synchronization needed to ensure coherent use of the counters.
Except that you've written in the comments you have to use AutoResetEvent (why?), so I guess you're stuck with Interlocked (no point in using lock if you're not going to take full advantage).
3.I don't understand why all the tasks are printed together, I expected each task to be printed when it is done and now when everything is done.
Because you have a bug. You should be creating a single Random instance and using it to determine the duration of every task. You can either compute the durations in the thread that creates each task, or you can synchronize access (e.g. with lock) and use the same Random object in multiple threads.
What you can't do is create a whole new Random object using the same seed value for every thread, because then each thread (or at least large blocks of them, depending on timing) is going to wind up getting the exact same "random" number to use as its duration.
You see all the output coming out together, because that's when it happens: all together.
(And yes, if you create multiple Random objects in quick succession, they will all get the same seed, whether you use DateTime.Now yourself explicitly, or just let the Random class do it. The tick counter used for the seed is not updated frequently enough for concurrently running threads to see different values.)
4.is the following code thread safe?
The code in question:
while (numberOfBs < 5)
{
bResetEvent.WaitOne();
numberOfBs++;
}
…is thread safe, because the only data shared between the thread executing that loop and any other thread is the AutoResetEvent object, and that object is itself thread-safe.
That is, for the usual understanding of "thread safe". I highly recommend you read Eric Lippert's article What is this thing you call "thread safe"? Asking if something is thread-safe is a much more complicated question that you probably realize.
In particular, while the code is thread-safe in the usual way (i.e. data remains coherent), as you note it is possible for more than one thread to reach the Set() call before the main thread can react to the first. Thus you may miss some notifications.
The task that requires taks A and B reach certain changes could be notified each time a task is done. When it gets notified it could check if the conditions are good and proceed only then.
Output:
Task 3 still waiting: A0, B0
B reached 1
Task 3 still waiting: A0, B1
A reached 1
Task 3 still waiting: A1, B1
B reached 2
Task 3 still waiting: A1, B2
B reached 3
Task 3 still waiting: A1, B3
A reached 2
Task 3 still waiting: A2, B3
B reached 4
Task 3 still waiting: A2, B4
B reached 5
Task 3 done: A2, B5
A reached 3
B reached 6
B reached 7
B reached 8
B reached 9
B reached 10
All done
Program:
class Program
{
static int stageOfA = 0;
static int stageOfB = 0;
private static readonly AutoResetEvent _signalStageCompleted = new AutoResetEvent(false);
static void DoA()
{
for (int i = 0; i < 3; i++) {
Thread.Sleep(100);
Interlocked.Increment(ref stageOfA);
Console.WriteLine($"A reached {stageOfA}");
_signalStageCompleted.Set();
}
}
static void DoB()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(50);
Interlocked.Increment(ref stageOfB);
Console.WriteLine($"B reached {stageOfB}");
_signalStageCompleted.Set();
}
}
static void DoAfterB5andA1()
{
while( (stageOfA < 1) || (stageOfB < 5))
{
Console.WriteLine($"Task 3 still waiting: A{stageOfA}, B{stageOfB}");
_signalStageCompleted.WaitOne();
}
Console.WriteLine($"Task 3 done: A{stageOfA}, B{stageOfB}");
}
static void Main(string[] args)
{
Task[] taskArray = { Task.Factory.StartNew(() => DoA()),
Task.Factory.StartNew(() => DoB()),
Task.Factory.StartNew(() => DoAfterB5andA1()) };
Task.WaitAll(taskArray);
Console.WriteLine("All done");
Console.ReadLine();
}
}

Threads - Simulation of execution time

I have two secondary threads,that executes the method WriteX as described below:
static void Main(string[] args)
{
ThreadStart one = new ThreadStart(WriteX);
Thread startOne = new Thread(one);
ThreadStart two = new ThreadStart(WriteX);
Thread startTwo = new Thread(two);
startOne.Start();
startTwo.Start();
Console.ReadKey(true);
}
public static void WriteX()
{
for (int i = 1; i <= 3; i++)
{
Console.WriteLine("Hello");
Thread.Sleep(1000);
}
}
( 1 ) How can i find the time taken (in milli seconds) by "startOne" and "startTwo" to complete its task?
( 2 ) I started the Thread (Start() ).Won't i need to stop the thread upon successful execution or will that be handled by the primary thread (Main() in this case) ?
(3) How can i print the message say , startOne is executing WriteX() method and startTwo is executing WriteX() method ?
In every serious logging framework, you can include the thread Id, or the thread name in the output message. If you just want to use the Console, you may have to manually append the current thread id/name to your message.
Like so:
public static void WriteX()
{
var sw = Stopwatch.StartNew();
for (int i = 1; i <= 3; i++)
{
Console.WriteLine("Hello");
Thread.Sleep(1000);
}
sw.Stop();
Console.WriteLine("{0} {1}",
Thread.CurrentThread.ManagedThreadId,
sw.Elapsed);
}
To name a thread, just use the Name property on the thread instance:
ThreadStart one = new ThreadStart(WriteX);
Thread startOne = new Thread(one);
startOne.Name = "StartOne";
//...
Console.WriteLine("{0} {1}", Thread.CurrentThread.Name, sw.Elapsed);
Also, when the method you pass as ThreadStart constructor argument finishes, the thread ends automatically. Use the Join method if you want to wait for a thread end in the main one.
Wrap WriteX() in something that saves the current time before and after (or simply do it at the begin and end of WriteX()) and print the difference at the end.
When the method passed to ThreadStart finishes, the thread terminates itself (and cleans itself up)
Again, wrap WriteX() in something that does the logging. I suggest to look at the source for ThreadStart to see how it's implemented and how you can extend/wrap it.
If you have no idea what I'm talking about, this article might help.
It depends on whether you want to get sum of execution times of two independent tasks or the biggest one. In first case you need to measure required time within WriteX. In the second case before startOne and stop measuring when both ar finished. Use Stopwatch in both cases.
Use Thread.Join to wait until both threads are finished.
Use parameterized start Thread.Start(object) and pass task name there.

Categories