LabWindows/CVI

Content Type
Programming Language
Current manual

Types of Data to Protect

Types of Data to Protect

Global variables, static local variables, and dynamically allocated memory are located in common memory areas that are accessible to all threads in a program. Make sure that you protect data stored in these types of memory locations against concurrent access from multiple threads to ensure that values are not corrupted. Function parameters and nonstatic local variables are located on the stack. The OS allocates a separate stack for each thread. Therefore, each thread gets its own copy of parameters and nonstatic local variables, so parameters and nonstatic local variables do not have to be protected against concurrent access. The following code shows which types of data must be protected against concurrent access by multiple threads.

int globalArray[1000];// Must be protected
static staticGlobalArray[500];// Must be protected
void foo (int i)// i does NOT need to be protected
int globalInt;// Must be protected

{

int localInt;// Does NOT need to be protected
int localArray[1000];// Does NOT need to be protected
int *dynamicallyAllocdArray;// Must be protected
static int staticLocalArray[1000];// Must be protected
dynamicallyAllocdArray = malloc (1000 * sizeof (int));

}

For example, consider a multithreaded program that increments an integer global counter variable from multiple threads as follows:

count = count + 1;

This code is executed as the following sequence of CPU instructions:

  1. Move the value in count into a processor register
  2. Increment the value in the processor register
  3. Write the value in the processor register back into count

Because the OS might interrupt a thread at arbitrary points in its execution, two threads executing this sequence of instructions could execute them in the following order (assume that count starts with the value 5):

Thread 1: Move the value in count into a processor register. (count = 5, register = 5)
Switch to Thread 2. (count = 5, register = ?)
Thread 2: Move the value in count into a processor register. (count = 5, register = 5)
Thread 2: Increment the value in the processor register. (count = 5, register = 6)
Thread 2: Write the value in the processor register back into count. (count = 6, register = 6)
Switch to Thread 1. (count = 6, register = 5)
Thread 1: Increment the value in the processor register. (count = 6, register = 6)
Thread 1: Write the value in the processor register back into count. (count = 6, register = 6)

Because thread 1 was interrupted before it could increment the value and write it back, the value of count is set to 6 instead of 7. The OS keeps a separate copy of the processor registers for each thread in the system. Even if you write the code as count++, you continue to have the same problem because the processor continues to execute the code as multiple instructions. Notice the particular timing condition that causes this failure. This means that your program might run correctly 1000 times for each time it fails. Empirical evidence has shown that multithreaded programs with incorrect data protection typically run correctly during testing but fail immediately when your customer installs and runs them.

Was this information helpful?