Synchronization

You can fix independent update sharing problems by synchronizing the execution of code that uses the same memory locations. The key idea is that when two or more tasks contain groups of operations which should not execute at the same time, there must be a lock which controls the execution of all of these groups of operations. Such a group of operations is called a transaction, and may be anything from a read/modify/write of a single variable to a collection of related modifications to multiple data structures.

Before beginning a transaction, a task must acquire the lock that controls it, and when the transaction is done, the task must release it. If one task has already acquired a lock, then another task that tries to acquire the same lock will stop executing until the first task has released it. This guarantees that two transactions controlled by the same lock cannot execute at the same time.

Use the Advisor lock annotations ANNOTATE_LOCK_ACQUIRE and ANNOTATE_LOCK_RELEASE to describe a transaction you intend to lock. Later, you will modify the lock annotations to actual code that implements a lock using the chosen parallel framework code:

void do_something()
{
    static bool initialized = false;
    ANNOTATE_LOCK_ACQUIRE(0);
    if (!initialized) {
        do_the_initialization();
        initialized = true;
    }
    ANNOTATE_LOCK_RELEASE(0);
    do_the_real_work();
}

Locks are identified by a lock address.

For more complete information about compiler optimizations, see our Optimization Notice.