Threads
Threads are a powerful mechanism for running multiple independent tasks, also known as parallel or concurrent processes. Even on a single-processor computer threads are useful. One processor can only do one thing at a time, but by giving small amounts of time to every process, a form of multi-tasking is achieved.Why threads instead of processes ?
Threads are often called lightweight processes. The creation of a new thread requires considerably less system resources than the creation of a new process because threads are much smaller and they share the variable space with the other threads, whereas processes carry their own environment around.
Threads behave like independent processes (they have their own program counter, stack and registers) but differ from truly independent programs in that they have a shared variable space which makes communication between threads easier than communication between independent processes and eases access to shared resources.
Applications of threads:
- I/O synchronisation, e.g. MIDI events from a user and real time audio events
- Client/server architecture
- Scheduler
- Task synchronisation, e.g. slow and fast tasks like user-interface and real-time audio
- Automatically exploiting multi-processor architectures
- Parallelising a complex task into multiple simpler simultaneous tasks
The following examples demonstrate several aspects of working with threads.
The Makefile
can be used to build all examples.
Create two threads that call the same (named) function and one thread
calling a lambda function
threads.cpp
Create two threads that share the same resource, in this case a counter
starting with a value of 0.
Thread 1 increments the counter, while thread 2 decrements it. Both threads
perform the same number of iterations, so the end result should be 0, but
because this example does not protect the counter for simultaneous access,
there is a possibility that one thread reads the value before the other has
written its new value. When threads are given time slices in which they can
perform a block of iterations, the error can become quite significant.
needs_mutex.cpp
In this example, the counter is protected by a mutex. The end result should
always be 0.
simplemutex.cpp
try_lock is a way to continue doing other things when a mutex you want
is not available. This function will not block.
You can come back later to check again if the mutex is free.
simple_try_lock.cpp
To be described: threading in the object oriented world, spin-lock, semaphores, exchanging data between threads, sending signals to threads.