Archive for December, 2011

Before we look at a multi-threaded program example, it is very, very important to have a clear understanding of the implications of introducing multi-threading in our program(s); we must understand when it makes sense and when it’s appropriate having additional thread(s) in our applications; this is critical because it may lead to real faster [parallel] execution or, we end up with a program that not only takes more time than it would having only one thread but, also impacts the overall performance due to overhead and synchronization switching among multiple execution contexts.

One of the simplest things we should be clear is that multi-threading per se does not mean programs run faster. Implementing multi-threads where we shouldn’t can actually cause opposite effects. Not all programs or tasks may be suitable for multi-threading implementations.

It makes sense having an additional thread when performing these tasks:

– Lengthy operations in the background.

– CPU intensive or time consuming operations.

– Tasks that would otherwise tie up our application interaction.

Having an additional thread to perform those operations in the background frees the main thread and keeps our application responsive to user interaction. A good example of this is Apple’s iTunes software; if you start playing a song you can keep doing things like downloading a podcast and synchronizing or visiting the app store while the song plays.

The following list is specific to the Microsoft .NET Framework and is not exhaustive but, it lists basic concepts we want to be aware of before writing our first multi-threaded programs. Many of these concepts apply in other programming environments as well and it is a good starting point to understand multi-thread programming.

1. A thread is an independent execution context, and it runs simultaneously along other threads.

2. A program starts in a single thread, created automatically by the CLR and operating system, the “main” thread.

3. A program becomes multi-threaded by creating additional threads.

4. The CLR assigns each thread its own memory stack so that local variables are kept separate.

5. Threads share data if they reference the same object instance.

6. Static variables offer another way to share data between threads.

7. Static variables are shared between all threads.

8. When reading/writing shared variables, only one thread should execute that code at a time.

9. Use an exclusive lock while reading/writing shared variables.

10. Code that is protected using an exclusive lock is called thread-safe.

11. When two threads simultaneously contend a lock, one thread waits, or blocks, until the lock becomes available.

12. Temporarily pausing, or blocking, is an essential feature in coordinating, or synchronizing the activities of threads.

13. A thread, while blocked, does not consume CPU time.

14. Multi-threading is managed internally by a thread scheduler.

15. On a single-core computer, a thread scheduler performs time-slicing – rapidly switching execution between each one of the active threads.

16. A time-slice is typically in the tens-of-milliseconds, much larger than the CPU overhead in switching contexts, typically a few-microseconds.

17. On a multi-core or multi-processor computer, multithreading is implemented with a mixture of time-slicing and genuine concurrency – where different threads run code simultaneously on different CPUs.

18. A thread has no control over when and where its execution is interrupted.

19. A common application for multi-threading is performing time-consuming tasks in the background.

20. In a non-UI application, such as a Windows Service, multi-threading makes particular sense when a task is potentially time-consuming because it is waiting for a response from another computer (such as an application server, database server, or client).

21. Another use for multi-threading is in methods that perform intensive calculations (CPU intensive).

22. An application can become multi-threaded in two ways: either by explicitly creating and running additional threads, or using a feature of the .NET framework that implicitly creates threads – such as BackgroundWorker, thread pooling, or a threading timer.

23. Having multiple threads does not in itself create complexity; it’s the interaction between the threads that creates complexity.

24. When heavy disk I/O is involved, it can be faster to have just one or two workers thread performing tasks in sequence, rather than having a multitude of threads each executing a task at the same time.

25. A thread, once ended, cannot be re-started.

26. By default, threads are foreground threads, meaning they keep the application alive for as long as any one of them is running.

27. Background threads don’t keep the application alive on their own, terminating immediately once all foreground threads have ended.

28. Changing a thread from foreground to background doesn’t change its priority or status within the CPU scheduler in any way.

29. Thread priority becomes relevant only when multiple threads are simultaneously active. public enum ThreadPriority { Lowest, BelowNormal, Normal, AboveNormal, Highest }

30. From .NET 2.0 onwards, an unhandled exception on any thread shuts down the whole application, meaning ignoring the exception is generally not an option. Hence a try/catch block is required in every thread entry method – at least in production applications – in order to avoid unwanted application shutdown in case of an unhandled exception.

Keep this list handy, it will help you remember things at the time of writing your multi-threaded programs.

If we wanted to chew and whistle at the same time, we would need two mouths not two cores. Can dryer and washer do work in parallel? Yes they can. On the same load? Obviously not.

For further reading about .NET Framework threads a very good reference is CodeNotes for VB.NET by Gregory Brill, Random House; pp. 74-85. For a more recent presentation about threads in the .NET Framework go to MSDN Managed Threading http://msdn.microsoft.com/en-us/library/3e8s7xdd.aspx and Managed Threading Best Practices http://msdn.microsoft.com/en-us/library/1c9txz50.aspx

Questo que lotro, salud!


Read Full Post »