The basic unit that we will deal with in this chapter is a thread. A thread is an independent context of execution within an operating system process. It has its own program counter and local data. A thread is the smallest unit of execution that can be scheduled. Most modern operating systems allow a single process to group multiple threads into a related set that shares some properties and keeps certain others private. A single thread is a sequence of computations and is the simplest testing situation. Techniques discussed in earlier chapters have "covered" the various entry points into and the paths through a single thread of computation. The techniques have accounted for alternative paths through the logic including the dynamic substitution of one piece of code for another. The basic complication introduced by having multiple threads arises when they share information or access data stores that are available to more than one thread. For concurrency to be of value, there should be as few dependencies between threads as possible. Dependencies imply that the order in which computations in the two threads occur matters. Since each thread is independently scheduled by the operating system, the developer must provide some mechanism to synchronize the threads so that the correct order is followed. Object-oriented languages provide some natural means of synchronization by hiding attributes behind interfaces and, in some cases, making threads correspond to objects. This means that synchronization is visible in the object interface (such as the synchronize keyword in Java) and that messaging is a key element in synchronization. In this environment, class testing does not detect many, if any, synchronization defects. It is only when a set of objects interact that the real opportunity to detect synchronization defects occurs. The case study that we have been using was originally written sequentially and the C++ version that can be downloaded from the Web is a sequential version. The Java version does introduce concurrency. Essentially, the MovablePiece objects are autonomous from the other computations in the game. They are in the sense that the Timer object maintains a separate thread and sends the tick() message to every MovablePiece object that is registered with it. The synchronization problem that must be examined is whether it is possible for the Timer thread to retain control of the processor and send the tick() message to a single object several times before the thread that manages the display can compute a collision, change the location of the object that was moved, and update the display. |