When writing a threaded application, it is important to understand the visibility and scope of various classes of storage.
Global storage that you declare in one of your application source files is visible to all other source files or modules in your application. All threads that run code in your application share the same global storage. This unintended sharing of storage is a common safety problem.
Static storage is global storage with visibility that is restricted to the source file, module, or function in which the storage or variable was declared. All threads that run code from that module share the same static storage.
Heap storage is allocated and deallocated dynamically by your application (for example, by malloc() and free() in C, or new and delete in Java™ or C++). All threads that run code in your application share the same heap.
If you give another thread a pointer to the heap storage that has been allocated (by storing the pointer in static or global storage, or by otherwise passing the pointer to another thread) that thread can use or deallocate the storage. This unintended sharing of storage is a common thread safety problem.
Automatic or local storage is allocated automatically by your language when you declare a variable that is private to a function, method, or subroutine. Local storage is not visible to other threads in the process. Each time those threads call the function, method, or subroutine, the thread allocates new versions of the automatic variables. Each thread gets its own automatic storage. A thread should not access automatic storage from another thread because of the complex serialization and synchronization issues involved.
The operating system further restricts the scope of global, static, and heap storage to the activation group that your application code is running in. This means that application code or threads running in different activation groups but using the same global or static variables access different versions of those variables and their storage. Similarly, heap storage allocated in one activation group might not be de-allocated in a different activation group although it can be used by different activation groups.
Some languages support only global or static storage classes for variables. These languages are not easy to use in threaded applications. You should not use threads in these languages.