user5491618
user5491618

Reputation:

using threads with a shared global variable

I'm having trouble coming up with an algorithm to ensure mutual exclusion while threads are accessing a shared global variable. I'm trying to write a threaded function that can use a global variable, instead of switching it to a local variable.

I have this code so far:

int sumGlobal = 0;

void sumArray(int** array, int size){

  for (int i=0; i<size; i++){
    for (int j=0; j<size; j++){
      sumGlobal += array[i][j];
    }
  }
}

int main(){
    int size = 4000;
    int numThreads = 4;

    int** a2DArray = new int*[size];
    for (int i=0; i<size; i++){
        a2DArray[i] = new int[size];
        for (int j=0; j<dim; j++){
          a2DArray[i][j] = genRandNum(0,100);
        }    
    }


    std::vector<std::future<void>> thread_Pool;
    for (int i = 0; i < numThreads; ++i) {

        thread_Pool.push_back( std::async(launch::async,
                        sumArray, a2DArray, size));
    }
}

I'm unsure of how to guarantee that sumGlobal is not rewritten with every thread. I want to update it correctly, so that each thread adds its value to the global variable when it's finished. I'm just trying to learn threading, and not be restricted to non-void functions.

Upvotes: 1

Views: 5132

Answers (2)

Miles Budnek
Miles Budnek

Reputation: 30569

If you don't want to use a synchronized object like std::atomic<int> as @Christophe suggests, you can use std::mutex and std::lock_guard to manually synchronize access to your sum.

int sumGlobal = 0;
std::mutex sumMutex;

void sumArray(...) {
    for(...) {
        for(...) {
            std::lock_guard<std::mutex> lock(sumMutex);
            sumGlobal += ...;
        }
    }
}

Keep in mind that all that locking and unlocking will incur quite a bit of overhead.

Upvotes: 1

Christophe
Christophe

Reputation: 73376

Make the variable atomic:

#include <atomic>
... 
std::atomic<int> sumGlobal {0};

An atomic variable is exempt from data races: it behaves well even when several threads are trying to read and write it. Wheteher the atomicity is implemented through mutual exclusion or in a lock free maner is left to the implementation. As you use += to atomically update the variable, there is no risk of having inconsistencies in your example.

This nice video explains you in much more detail what atomics are, why they are needed, and how they work.

You could also keep your variable as they are and use a mutex/lock_gard to protect it, as explained my @Miles Budnek. The problem is, that only one thread at a time can execute code protected by the mutex. In your example, this would mean that the processing in the different threads would not really work concurently. The atomic approach should have superior performance : one thread may still compute indexes and read the array while the other is updating the global variable.

Upvotes: 2

Related Questions