Feeds:
Posts
Comments

Posts Tagged ‘multithreading’

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!

Advertisements

Read Full Post »

Whenever we create our first program we have no idea about what multithreading is or what a thread is for that matter, and no one cares explaining it at the time, or so it seems. However, whenever we create or first program we are already programming using threads, yes one thread at least.

A thread, in programming, is not a physical thing or something inside the computer. It is jut a term to refer to a programming concept or technique.

When we run our first best program, the operating system loads it (accommodates our program in memory), then the computer starts executing its instructions one after another, one at a time, and if there are no more instructions to execute the computer finishes execution, and our program terminates. Done deal, the program ended. So what?

Let me see if this explains it…. That was a thread of execution. Some people also call it a context of execution.

Typically we will add a loop in our program so that the computer keeps it loaded and keeps “running” those instructions inside the loop. Whenever the user decides to leave the program we would break out of the loop and our program would then terminate and exit. That’s it. Only one executing thread but a continuously running thread.

How did I know a program is using one thread? I didn’t. It turns out that when the operating system loads our program it will usually create a process for it, and then it creates a thread or context to execute whatever we wrote in our program; this thread is usually called the main thread or the main context of execution. That easy…, thread programming! Single-thread programming if you wish.

So what?? Well, if we want to do multi-threading or multi-thread programming, we have to create any additional threads programmatically (manually); the operating system will create only one for us, the main one but, any additional threads have to be created by the programmer. Don’t worry, you don’t have to pay a penny to create additional threads in your program. Additional threads are free… Cool!

Ok I see it….. If I create an additional thread in my program then I am doing multi-threading programming. Yep.

And why would I want to create an additional thread in my program?

There are many reasons for multi-threading but let me mention just one. Often times we have to process long running or time consuming tasks in our program (for instance, downloading big files) but, we don’t want to have users waiting for that long running task to finish and being unable using our program. Thus, we want to have the computer execute time consuming tasks in a separate thread of execution; that way users can keep working with the main program at the same time a file is downloading.

If we want to create an additional thread in our program, we have to provide the starting point of execution for that thread, which is usually the name of a function in our program that we want that thread to execute.

Then again…..

When we create our first best thread in our formerly single-threaded program, the operating system will accommodate the additional thread in memory, and the computer will start executing the instructions contained in the function we specified when we give it the go ahead (usually calling Start()), one after another, one at a time, and if there are no more instructions to execute in our function the context of execution terminates. Done deal, the thread is finished and very likely disposed of by the operating system. Thank you for participating!

Yep; if we do not write a loop (which we would usually do for most long processing tasks) in our ‘to be executed by an additional thread’ function, the computer will run whatever there’s inside that function until the end and the thread will end. That’s it; one less thread in our program. This means two ways of ending your threads; one is by not having a loop in the function executed by the thread; second one is by having a loop in the function and breaking out of the loop when a certain condition is satisfied, which will end the thread automatically. As far as I know, programming languages that support multi-threading have no function to stop a running thread. Stopping a running thread will depend on whatever we write inside the function executed by the thread.

Starting the execution of an additional thread is not the same as calling a function in our program, nope; starting the execution of an additional thread in our program is starting execution of an additional context “in parallel” (or so it seems) with our main context. The computer will continue with the execution of our main thread right after we start our additional thread; at this point the computer will be running the two threads in our program, two execution contexts, the main context and our new thread context. Wonderful! And the operating system will take care of switching execution contexts back and forth from the main thread to the new thread; we as programmers don’t have to worry about switching between threads after we have started additional threads in our program. Fantastic!

Note that if there’s no loop in our main thread and we created an additional thread having a loop, our main program will end executing and our extra thread with it, most likely; the garbage collector will probably take care of that additional thread once its own loop ends, but who knows what will happen; I don’t know. It will depend on the programming system you are using.

The “complexity” of multi-threading starts with the “execution in parallel” part. For one, you the programmer is responsible of avoiding concurrency conflicts when your different threads try to change or access the value of a ‘common to all threads variable’ (commonly known as global variable); remember our threads are “executing in parallel” and we won’t know when and in what order the computer will switch execution context (switching execution from one thread to another thread). Programming languages that support multi-threading have functions that we can use to synchronize our threads, that is, having our threads access global variables in a synchronized manner. However, your program and your threads should run fine if you manage to keep your threads (contexts of execution) from touching other threads’ belongings, or if you keep your threads in sync when touching ‘common to all threads’ variables, also known as static variables.

I think that’s very much all there is to understand multi-threading (remember it is “executing in parallel”). If  you are creating your first program and you understood this explanation you should be able to create multi-threading programs from now on. Good luck.

Questo, que lotro…, salud!

Read Full Post »