Race conditions in threads despite mutexlocking - c++

This code calculates the sum of all integers in an array, evenly dividing the work between multiple threads. However every once in a while the thread numbers as well as the localsum of the thread are messed up. I am assuming it's because void* param and globalindex are accessed by multiple threads at the same time. What does not make sense is the fact that it happens, even though I mutexlocked every global variable in this code.
How do I fix this?
#include<string>
#include<iostream>
#include<fstream>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
int y =0;
int sum=0;
int array[1000000];
int x=0;
int leftoverHandle = 0;
int globalindex = 0;
int eachThreadHandles =0;
void* add(void* param){
pthread_mutex_lock(&mutex);
int localindexup = globalindex + eachThreadHandles;
int localindexdown = globalindex;
int localsum=0;
long localparam = (long)param;
if(y != leftoverHandle ){
localindexup++;
y++;
}
pthread_mutex_unlock(&mutex);
while(localindexdown<localindexup){
pthread_mutex_lock(&mutex);
sum = sum+array[localindexdown];
localsum = localsum+array[localindexdown];
localindexdown++;
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);
globalindex = localindexdown;
printf("Thread %ld", localparam);
printf(": %d\n", localsum);
pthread_mutex_unlock(&mutex);
}
int main(int argc, char ** argv){
if(argc != 3){
cout<<"Incorrect number of argument";
exit(1);
}
string line;
string f = argv[1];
const char *filename = f.c_str();
int maxthreads = atoi(argv[2]);
FILE* inFile = fopen(filename,"r");
int i=0;
if(inFile == NULL){
cout<<"fopen failed"<<endl;
}
fscanf(inFile, "%d",&i);
while(!feof(inFile)){
array[x]=i;
x +=1;
fscanf(inFile,"%d",&i);
}
fclose(inFile);
pthread_t id[maxthreads];
leftoverHandle = x%maxthreads;
eachThreadHandles = (x - leftoverHandle)/maxthreads;
for(long i=0; i< maxthreads;i++){
long status = pthread_create(&id[i], NULL, add, (void*) i);
if(status){
printf("Error creating thread! \n");
exit(0);
}
}
for(long i=0; i<maxthreads;i++){
pthread_join(id[i], NULL);
}
cout<<"Sum="<<sum<<endl;
return 0;
}

The problem is that you are not updating globalindex right after initializing localindexup and localindexdown per each thread, i.e in the first critical section.
You have three critical sections in your code.
Imagine that thread0 runs the first critical section, then thread1 preempts thread0 right after thread0 releases the lock of the first critical section. But because you are setting globalindex to localindexdown in the third critical section, not the first one, thread1 will still see globalindex=0, just like thread0, so it is going to recalculate the same sum as thread0. You should put globalindex = localindexdown; into the first critical section.
Actually there is no need for the third critical section at all:
pthread_mutex_lock(&mutex);
int localindexup = globalindex + eachThreadHandles;
int localindexdown = globalindex;
int localsum=0;
long localparam = (long)param;
if(y != leftoverHandle ){
localindexup++;
y++;
}
globalindex = localindexdown; //<--- MOVED HERE
pthread_mutex_unlock(&mutex);
And forget my comment about the loop, I made a mistake: while(localindexdown<localindexup) can be safely preempted because the variables are not shared among threads. You can just improve the performance a bit by reducing the mutexed region to include only shared data:
while(localindexdown<localindexup)
{
pthread_mutex_lock(&mutex);
sum = sum+array[localindexdown];
pthread_mutex_unlock(&mutex); //<--- MOVED HERE
localsum = localsum+array[localindexdown];
localindexdown++;
}

Related

Can't tell if Mutex Lock is kicking in or not?

I'm working on a college assignment and have been tasked with showing a basic mutex lock example. I've never worked with threads in any form, so I'm a total beginner working with POSIX threads in C++.
What I'm trying to get the program to do is create 1000 threads that increment a global integer by 1000.
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <thread>
pthread_t threadArr[1000];
pthread_mutex_t lock;
// Global int to increment
int numberToInc = 0;
void* incByTwo(void*)
{
pthread_mutex_lock(&lock);
for(int j = 0; j < 1000; j++){
numberToInc += 1;
}
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
//Creates 1000 threads with incByTwo func
for(int i = 0; i < 1000; i++){
pthread_create(&threadArr[i], NULL, incByTwo, NULL);
}
std::cout << "\n" << numberToInc << "\n";
return 0;
}
The following produces a series of different results, obviously because the threads are executing concurrently, right?
Now, I've gotten it to work correctly by inserting
for(int i = 0; i < 1000; i++){
pthread_join(threadArr[i], NULL);
}
After the thread creation loop, but then removing the mutex locks, it still works. I've been trying to piece out how pthread_join works but I'm a little lost. Any advice?
Sorted a way to show the mutex lock in action. So when I output the global var in the function, without mutex locks it has the potential to show the results out of order.
Running the number range with mutex locks, out looks like:
1000
2000
3000
... (etc)
10000
With mutex locks removed, the output can vary in the order.
E.g.
1000
2000
4000
6000
3000
5000
7000
8000
9000
10000
While the final result of the three threads is correct, the sequence is out of order. In the context of this program it doesn't really matter but I'd imagine if it's passing inconsistently sequenced values it messes things up?
pthread_t threadArr[10];
pthread_mutex_t lock;
int numberToInc = 0;
void* incByTwo(void*)
{
pthread_mutex_lock(&lock);
for(int j = 0; j < 1000; j++){
numberToInc += 1;
}
std::cout << numberToInc << "\n";
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
for(int i = 0; i < 10; i++){
pthread_create(&threadArr[i], NULL, incByTwo, NULL);
}
pthread_join(threadArr[0], NULL);
return 0;
}

Is there a race condition when one thread is constantly querying a variable from memory while another thread updates it?

I have the following code
#include <stdio.h>
#include <thread>
#include <mutex>
class A
{
public:
A(int n) : num_workers(n) {
counter_lock = new std::mutex();
threads = new std::thread[num_workers];
for (int i = 0; i < num_workers; i++) {
threads[i] = std::thread(&A::run, this);
}
}
~A() {
delete counter_lock;
}
void start() {
go = true;
counter = 0;
total = 1000000;
while (counter < total) {};
for (int i = 0; i < num_workers; i++) {
threads[i].join();
}
}
void run() {
printf("Spinning\n");
while(1) {
if (go) {
int i;
counter_lock->lock();
i = counter++;
counter_lock->unlock();
if (i >= total) break;
}
}
printf("Done\n");
}
private:
std::mutex* counter_lock;
std::thread* threads;
int num_workers;
int counter;
int total;
bool active;
bool go;
};
int main() {
A a = A(10);
a.start();
}
In the constructor of A I create a thread pool of num_workers. They are all executing a function A::run which simply waits until it gets a signal to go and then starts incrementing the counter. The function start is meant to be synchronous with whomever called it, so in this case it should be synchronous with main. Therefore, it just idles until the counter reaches total after issuing the signal to go to all the worker threads.
The code works as expected. The counter ends up at 10000010 which makes sense because each of the 10 threads have incremented the counter once before quitting.
Is there a race condition here that I'm not noticing? Is the fact that I'm reading counter in the while(counter < total) {} loop without a lock causing any problems?
Thanks for any advice.
EDIT: I replaced the while (counter < total) {} loop with the following, perhaps more thread safe, implementation. But, very rarely, it still ends up looping forever since the value of counter hasn't updated.
while (1) {
int c;
counter_lock->lock();
c = counter;
counter_lock->unlock();
if (c >= total) break;
};

Suspected memory leak with _beginthread

So, i have some issues with i suspect a memory leak, in order to test i wrote this small code. By commenting the following line:
printf("Calc index: %d\n", ArrLength);
the code runs well. But when i uncomment it, the program crashed after a couple thousand threads.. When i use try/catch, the program just crashed inside the try function. Anyone who can help me out here?
#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <mutex>
#include <windows.h>
using namespace std;
typedef struct {
int StartNode;
int EndNode;
int GangID;
int MemberID;
int ArrLength;
int arr[10000];
}t;
t *arg;
mutex m;
void myFunc(void *param) {
m.lock();
printf("Calculate thread started\n");
t *args = (t*)param;
int StartNode = args->StartNode;
int EndNode = args->EndNode;
int GangID = args->GangID;
int MemberID = args->MemberID;
int ArrLength = args->ArrLength;
printf("Calc index: %d\n", ArrLength);
free(args);
m.unlock();
}
int main()
{
for (int i = 0; i < 1000000; i++)
{
HANDLE handle;
arg = (t *)malloc(sizeof(t));
arg->StartNode = 2;
arg->EndNode = 1;
arg->GangID = 1;
arg->MemberID = 1;
arg->ArrLength = 5;
for (int j = 0; j < 10000; j++)
{
arg->arr[j] = j;
}
handle = (HANDLE)_beginthread(myFunc, 0, (void*)arg);
}
cin.get();
return 0;
}
Well, let do some calc. Your t struct has 40020 bytes per instance. You do allocate it 1M times that causes about 40 Gb allocated in total. And this is not all the memory required because each thread is not for free. By default, Windows allocates 1Mb stack per thread that gives you 1 Tb (one terabyte) of memory required just to let the threads live.
So, total memory amount is something like 1040 Gb. Do you really intend that?

Mutex for two threads in C++

I've created two threads that use a variable declared in main via pthread_create's last argument. I want thread2 to use modify the value of that variable after thread1 is done with a set of particular instructions. I know how we can use mutex in one thread but how about two or more threads?
Refer to the following code:
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#define NUM 6
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *even(void *arg)
{
int sum = 0;
int count = 0;
for (int i = 1; count < NUM/2; i++)
{
if( !(i % 2) )
{
count++;
sum += i;
}
}
cout << "In Even Thread: " << sum << endl;
pthread_mutex_lock(&mutex);
*((int*)arg) = sum;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
void *odd(void *arg)
{
int sum = 0;
int count = 0;
for (int i = 1; count < NUM/2; i++)
{
if( i % 2 )
{
count++;
sum += i;
}
}
cout << "In Odd Thread: " << sum << endl;
pthread_cond_wait(&cond, &mutex);
*((int*)arg) = *((int*)arg) + sum;
}
int main()
{
int mainSum = 0;
pthread_t tidO, tidE;
pthread_create(&tidO, NULL, odd, (void *)&mainSum);
pthread_create(&tidE, NULL, even, (void *)&mainSum);
pthread_join(tidO, NULL);
pthread_join(tidE, NULL);
cout << "Sum of first " << NUM << " Natural Numbers: " << mainSum << endl;
return 0;
}
You should lock mutex before accessing the variable and unlock after you finish you finish you job with the variable. Use lock_guard to keep mutex locked and use brackets for lock_guard lifetime. http://www.cplusplus.com/reference/mutex/lock_guard/
std::mutex mtx; //global mutex
int v; //global variable;
int k;
...
//repeat this code in each thread to access the variable
{
std::lock_guard<std::mutex> lck (mtx);
//access the variable;
k = v; //read global variable or
v = k; //write
}
Your use case needs a condition variable combined with a mutex.
http://en.cppreference.com/w/cpp/thread/condition_variable
You should create mutex in same place as shared variable. In your case it is main function.
Then you need to share this mutex in all threads which are accessing shared variable.
You can share this mutex over global variable or better in same attribute as shared variable. But you will have to define structure where you place variable and mutex together.
Update
You should lock mutex pthread_mutex_lock(&mutex); before pthread_cond_wait(&cond, &mutex);
The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.

Double free or corruption (!prev) error when working with threads and mutex

I've got simple c++ code that firstly creates 4 threads and then sends 1000 times number 1 to the c++ queue followed by four 0. Each of these threads tries to read from that queue and when any thread reads 0, it terminates and prints its local sum. If it reads 1 then it simply adds 1 to the sum. The reading is protected with mutex. Code works as intended in 4 out of 5 times, but sometimes I get double free or corruption (!prev) error... ...Abort core dumped. I've also debugged the code with gdb but only got received signal SIGABRT, Aborted ... ...at raise.c: No such file or directory". I'm not explicitly allocating or deallocating any memory. What could be causing the problem?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
std::queue<int> my_queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *process(void *arg){
int sum = 0;
while(1){
if(!my_queue.empty()){
pthread_mutex_lock(&mutex);
if (my_queue.front() == 1){
sum += 1;
my_queue.pop();
pthread_mutex_unlock(&mutex);
}
else{
my_queue.pop();
printf("Sum: %d\n", sum);
pthread_mutex_unlock(&mutex);
break;
}
}
}
return arg;
}
int main(void){
pthread_t id[4];
for(int i = 0; i < 4; i++){
if (pthread_create(&id[i], NULL, process, NULL) != 0){
fprintf(stderr, "%s\n", "Error creating thread!");
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < 1000; i++){
my_queue.push(1);
}
for (int i = 0; i < 4; i++){
my_queue.push(0);
}
for (int i = 0; i < 4; i++){
pthread_join(id[i], NULL);
}
return EXIT_SUCCESS;
}
You have two problems:
Firstly you are pushing onto the queue without holding the lock, secondly you are testing if the queue is empty without holding the lock.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
std::queue<int> my_queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *process(void *arg){
int sum = 0;
bool keep_going = true;
while(keep_going){
pthread_mutex_lock(&mutex);
if(!my_queue.empty()){
if (my_queue.front() == 1){
sum += 1;
}
else{
keep_going=false;
}
}
my_queue.pop();
pthread_mutex_unlock(&mutex);
}
printf("Sum: %d\n", sum); // Don't do IO while holding a lock!
return arg;
}
int main(void){
pthread_t id[4];
// Initialize queue *before* creating threads.
for (int i = 0; i < 1000; i++){
my_queue.push(1);
}
for (int i = 0; i < 4; i++){
my_queue.push(0);
}
// Create threads
for(int i = 0; i < 4; i++){
if (pthread_create(&id[i], NULL, process, NULL) != 0){
fprintf(stderr, "%s\n", "Error creating thread!");
exit(EXIT_FAILURE);
}
}
// Join them.
for (int i = 0; i < 4; i++){
pthread_join(id[i], NULL);
}
return EXIT_SUCCESS;
}
If you want to add to the queue after creating the threads, you need something like:
pthread_mutex_lock(&mutex);
my_queue.push(value);
pthread_mutex_unlock(&mutex);
Inside the for-loops. Also, there is then a real chance of the queue emptying before you get to the zeros. Either do it properly by waiting on semaphores, or the queue loop needs to becomes something like:
pthread_mutex_lock(&mutex);
if(my_queue.empty()){
pthread_mutex_unlock(&mutex);
usleep(1);
pthread_mutex_lock(&mutex);
} else {
Where the thread will briefly sleep to let the queue fill up.
Also, you are writing in C++. Learn to write a RAII class to call pthread_mutex_lock and unlock.