mutex and its effect on execution time (and cpu usage)

时间:2015-07-28 16:40:08

标签: linux multithreading pthreads mutex cpu-usage

I wrote a very simple test program to examine efficiency of pthread mutex. But I'm not able to analyse the results I get. (I can see 4 CPUs in Linux System Monitor and that's why I have at least 4 active threads, because I want to keep all of them busy.) The existence of mutex is not necessary in the code.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>    

pthread_mutex_t lock1, lock2, lock3, lock4;

void do_sth() { /* just open a files, read it and copy to another file */ 
    int i;
    for (i = 0; i < 1; i++) {        
        FILE* fp = fopen("(2) Catching Fire.txt", "r");
        if (fp == NULL) {
            fprintf(stderr, "could not open file\n");
            exit(1);
        }
        char filename[20];
        sprintf(filename, "a%d", (int)pthread_self());
        FILE* wfp = fopen(filename, "w");
        if (wfp == NULL) {
            fprintf(stderr, "could not open file for write\n");
            exit(1);
        }
        int c;
        while (c = fgetc(fp) != EOF) {
            c++;
            fputc(c, wfp);
        }
        close(fp);
        close(wfp);
    }

}
void* routine1(void* param) {
    pthread_mutex_lock(&lock1);
    do_sth();
    pthread_mutex_unlock(&lock1);
}
void* routine2(void* param) {
    pthread_mutex_lock(&lock2);
    do_sth();
    pthread_mutex_unlock(&lock2);
}
void* routine3(void* param) {
    pthread_mutex_lock(&lock3);
    do_sth();
    pthread_mutex_unlock(&lock3);
}
void* routine4(void* param) {
    pthread_mutex_lock(&lock4);
    do_sth();
    pthread_mutex_unlock(&lock4);
}

int main(int argc, char** argv) {        
    int i ;
    pthread_mutex_init(&lock1, 0);
    pthread_mutex_init(&lock2, 0);
    pthread_mutex_init(&lock3, 0);
    pthread_mutex_init(&lock4, 0);

    pthread_t thread1[4];
    pthread_t thread2[4];
    pthread_t thread3[4];
    pthread_t thread4[4];

    for (i = 0; i < 4; i++)
        pthread_create(&thread1[i], NULL, routine1, NULL);
    for (i = 0; i < 4; i++)
        pthread_create(&thread2[i], NULL, routine2, NULL);
    for (i = 0; i < 4; i++)
        pthread_create(&thread3[i], NULL, routine3, NULL);
    for (i = 0; i < 4; i++)
        pthread_create(&thread4[i], NULL, routine4, NULL);

    for (i = 0; i < 4; i++)
        pthread_join(thread1[i], NULL);
    for (i = 0; i < 4; i++)
        pthread_join(thread2[i], NULL);
    for (i = 0; i < 4; i++)
        pthread_join(thread3[i], NULL);
    for (i = 0; i < 4; i++)
        pthread_join(thread4[i], NULL);
    printf("Hello, World!\n");
}

I execute this program in two ways, with and without all the mutex. and I measure time of execution (using time ./a.out) and average cpu load (using htop). here is the results:

first: when I use htop, I can see that loadavg of the system considerably increases when I do not use any mutex in the code. I have no idea why this happens. (is 4 active threads not enough to get the most out of 4 CPUs?)

second: It takes (a little) less time for the program to execute with all those mutex than without it. why does it happen? I mean, it should take some time to sleep and wake up a thread.

edit: I guess, when I use locks I put other threads to sleep and it eliminates a lot of context-switch (saving some time), could this be the reason?

1 个答案:

答案 0 :(得分:0)

You are using one lock per thread, so that's why when you use all the mutexes you don't see an increase in the execution time of the application: dosth() is not actually being protected from concurrent execution.

Since all the threads are working on the same file, all they should be accessing it using the same lock (otherwise you will have incorrect results: all the threads trying to modify the file at the same time).

Try running again the experiments using just one global lock.