Mutexinit, MutexLock, and Mutexunlock
In thread-parallel execution mutexes can be used to protect a common block or a common file from being updated by multiple threads at the same time. Abaqus provides 100 predefined mutexes for use in user subroutines. They are referenced simply by number (1–100).
Mutexes need to be initialized before they can be used. For example, MutexInit(1) initializes mutex 1. It is best to initialize mutexes at the very beginning of the analysis in user subroutines, such as user subroutines UEXTERNALDB and VEXTERNALDB.
Once initialized, mutexes can safeguard sensitive sections of the code against concurrent access. For example, MutexLock(1) and MutexUnlock(1) will respectively lock and unlock mutex 1.
Each mutex can protect a shared resource or a logical group of resources that are always accessed together. Different mutexes are provided so that users can protect a variety of shared resources or objects. For example, one mutex can protect a file and another mutex can protect common block variables. Thus, accessing a file can happen simultaneously with updating common block variables; but no two threads can write to the file at the same time, and no two threads can update the variables at the same time.
To make data transfer and accumulation easier and safer between user subroutines in a multi-threaded environment, Abaqus provides utility functions to create dynamic storage in the form of thread-local arrays, which are private to each thread, and global arrays, which are shared. Any number of arrays of any size can be created at run time. Global arrays are accessible from all user subroutines and all threads. Thread-local arrays are private and exist only within the scope of each thread. They are accessible to all user subroutines running in that thread but not across threads. Since they are not visible to neighboring threads, they do not need to be protected from concurrent access. They are designed as a thread-agnostic replacement for the COMMON BLOCKS and SAVE variables (see Allocatable Arrays for more information).
All other techniques commonly used in parallel programming can also be employed; for example, restricting all file operations only to thread 0. Oftentimes, these alternatives are preferable to using mutexes because they may provide better performance.
Utility Routine Interface
Fortran: #include <SMAAspUserSubroutines.hdr> ! Initialization in UEXTERNALDB/VEXTERNALDB call MutexInit( 1 ) ! initialize Mutex #1 ! Use in all other user subs after being initialized call MutexLock( 1 ) ! lock Mutex #1 < critical section : update shared variables > call MutexUnlock( 1 ) ! unlock Mutex #1 C++: #include <SMAAspUserSubroutines.h> // Initialization in UEXTERNALDB/VEXTERNALD MutexInit( 1 ); // initialize Mutex #1 // Use in all other user subs after being initialized MutexLock( 1 ); // lock Mutex #1 < critical section : update shared variables > MutexUnlock( 1 ); // unlock Mutex #1 NOTE: IDs are arbitrary chosen by the user, from the pool of 1-100. Other threads, when encountering a locked mutex, will sleep. Once the first entering thread unlocks the mutex and leaves, other threads will be able to come in and execute the critical section (one at a time).