Tuesday, September 12, 2017

Multi-threading & Task Parallel Library - II

How Threading works


  • Multi threading is managed by thread scheduler, a function CLR delegates to operating system.
  • On a single-processor computer, a thread scheduler performs time-slicing — rapidly switching execution between each of the active threads.
  • On a multi-processor computer, multi-threading is implemented with a mixture of time-slicing and genuine concurrency, where different threads run code simultaneously on different CPUs. It’s almost certain there will still be some time-slicing, because of the operating system’s need to service its own threads — as well as those of other applications.
  • A thread is said to be preempted when its execution is interrupted due to an external factor such as time-slicing. In most situations, a thread has no control over when and where it’s preempted.
  • thread is the basic unit to which the operating system allocates processor time.
  • process, in the simplest terms, is an executing program which provides resource to running thread.
Different ways to cretate thread and invoke it.

Using Delegate
Public delegate void Threadstart()
Thread t = new Thread(new Threadstart(MethodName())
t.start();

Directly via Method name
Thread t = new Thread( MethodName())
t.start();

Using Lambda Expression

Thread t = new Thread ( () => Console.WriteLine ("Hello!") );
 t.Start();




Multi-threading & Task Parallel Library - I


Introduction
  • A thread is an independent execution path, able to run simultaneously with other threads. 
  • Once started, a thread’s IsAlive property returns true, until the point where the thread ends. 
  • A thread ends when the delegate passed to the Thread’s constructor finishes executing. Once ended, a thread cannot restart.
  • The CLR assigns each thread its own memory stack so that local variables are kept separate. 
  • Separate copy of the cycles variable is created on each thread's memory stack.

class ThreadTest
{
  static void Main()
  {
    Thread t = new Thread (WriteY);          // Kick off a new thread
    t.Start();                               // running WriteY()
 
    // Simultaneously, do something on the main thread.
    for (int i = 0; i < 1000; i++) Console.Write ("x");
  }
 
  static void WriteY()
  {
    for (int i = 0; i < 1000; i++) Console.Write ("y");
  }
}

class ThreadTest
{
  bool done;
 
  static void Main()
  {
    ThreadTest tt = new ThreadTest();   // Create a common instance
    new Thread (tt.Go).Start();
    tt.Go();
  }
 
  // Note that Go is now an instance method
  void Go() 
  {
     if (!done) { done = true; Console.WriteLine ("Done"); }
  }
}
Main thread and Child thread can share data by using static variable or invoking method using object as in above example.
Since multiple thread if trying to do same operation or change same variable, there is possibility of conflicts , to avoid that we obtaining exclusive lock.
class ThreadSafe 
{
  static bool done;
  static readonly object locker = new object();
 
  static void Main()
  {
    new Thread (Go).Start();
    Go();
  }
 
  static void Go()
  {
    lock (locker)
    {
      if (!done) { Console.WriteLine ("Done"); done = true; }
    }
  }
}
A thread, while blocked, doesn't consume CPU resources.
Using JOIN we can force a thread to wit until other completes.
static void Main()
{
  Thread t = new Thread (Go);
  t.Start();
  t.Join();
  Console.WriteLine ("Thread t has ended!");
}
 
static void Go()
{
  for (int i = 0; i < 1000; i++) Console.Write ("y");
}
Thread.Sleep(0) relinquishes the thread’s current time slice immediately, voluntarily handing over the CPU to other threads. Framework 4.0’s new Thread.Yield() method does the same thing — except that it relinquishes only to threads running on the same processor.
If inserting Thread.Yield() anywhere in your code makes or breaks the program, you almost certainly have a bug.