Multi-threaded servers are tricky to program, because multiple threads can access the process's memory simultaneously. A task that requires several steps may fail if the set of steps is interrupted before completion.
Nearly all modern operating systems, such as Windows95, NT and Unix support pre-emptive multi-tasking. Older systems, such as Windows 3.1 and the Mac, support cooperative multi-tasking, as do many of the shells that programmers put around DOS to run more than one DOS program at a time.
In pre-emptive multi-tasking, the CPU and the operating system work together to support multi-threaded applications by interrupting one task in order to begin another. This interruption is outside the control of the programmer and may come between any two machine instructions.
In cooperative multi-tasking the programmer must yield control to the system, and methods are never "pre-empted". Cooperative multi-threading is easier to program, but more prone to poor performance. All modern operating systems are pre-emptive.
If your operating system supports pre-emptive multi-tasking, the thread cannot know when it might be interrupted. A given thread may be interrupted between any two machine instructions, and if your code is not thread-safe, this can be disastrous.
Thread-safe means the application designed so that no harm can come from being interrupted in mid-operation
A task that tests and sets a flag in two sequential instructions is not guaranteed to succeed. A second thread may set the flag in between the two instructions. In this case, the update from the second thread is lost. (For example, thread A makes a test and gets the value 1. Thread B sets the value to 5. Thread A writes back 2. The value is at 2 and Thread B's change is lost.)
To create a thread-safe application, you must be able to synchronize access to critical objects, so that one thread cannot corrupt the work of another. Synchronization mechanisms were created to solve this problem, and we will come to these later in this chapter.