用Pthread實現多執行緒操作

丟的錢找到了發表於2018-03-23
學習Pthread時的筆記和demo,感謝各路大神的分享

pthread_create

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

void * thread(void *arg)
{
    printf("arg is %d.\n", *(int *)arg);
    *(int *)arg = 123456;
    return arg;
}

int main(int argc, char const *argv[])
{
    pthread_t tid;
    int arg = 111111;

    int res = pthread_create(&tid, NULL, thread, &arg);
    if (res != 0)
    {
        perror("pthread_create");
        return -1;
    }

    printf("main thread.\n");

    int *thread_res = NULL;
    res = pthread_join(tid, (void **)&thread_res);
    if (res != 0 || !thread_res)
    {
        perror("pthread_join");
        return -1;
    }

    printf("thread return val = %d\n", *thread_res);

    return 0;
}

複製程式碼

join detach

    執行緒的合併是一種主動回收執行緒資源的方案。當一個程式或執行緒呼叫了針對其它執行緒的pthread_join()介面,就是執行緒合併了。這個介面會阻塞呼叫程式或執行緒,直到被合併的執行緒結束為止。當被合併執行緒結束,pthread_join()介面就會回收這個執行緒的資源,並將這個執行緒的返回值返回給合併者。

    與執行緒合併相對應的另外一種執行緒資源回收機制是執行緒分離,呼叫介面是pthread_detach()。執行緒分離是將執行緒資源的回收工作交由系統自動來完成,也就是說當被分離的執行緒結束之後,系統會自動回收它的資源。因為執行緒分離是啟動系統的自動回收機制,那麼程式也就無法獲得被分離執行緒的返回值,這就使得pthread_detach()介面只要擁有一個引數就行了,那就是被分離執行緒控制程式碼。

    呼叫pthread_create()函式,執行緒要麼是合併的(預設)要麼是分離的。如果是合併屬性的執行緒,那麼必須使用pthread_join()等待結束,否則所佔用的資源不會得到釋放從而造成資源洩露。而分離屬性的執行緒在結束的時候會自動釋放所佔用的資源。

    一個合併屬性執行緒只能用一個pthread_join()函式來等待結束。如果有多個pthread_join函式則只有第一個執行到的有效,其他的都會直接返回錯誤。

detach demo

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

void * func(void *a)
{
    printf("other thread\n");
    return a;
}

int main(int argc, char *argv[])
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    
    //PTHREAD_CREATE_DETACHED(分離的)PTHREAD_CREATE_JOINABLE(可合併的,也是預設屬性)
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    
    pthread_t th;
    pthread_create(&th, &attr, func, NULL);
    
    printf("main thread\n");
    
    pthread_attr_destroy(&attr);

    return 0;
}
複製程式碼

join demo

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

void * func(void *arg)
{
    int tid = (int)pthread_self();
    printf("tid %d start\n",tid);
    double result = 0.0;
    for (int i = 0;i < 100000;++i)
    {
        result += (double)random();
    }
    printf("tid %d result = %e\n",tid,result);
    printf("tid %d end\n",tid);
    
    return NULL;
}

int main(int argc, char const *argv[])
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
    pthread_t thread[5];
    int len = sizeof(thread)/sizeof(pthread_t);
    
    for (int i = 0;i < len;++i)
    {
        int res = pthread_create(&thread[i], &attr, func, NULL);
        if (res != 0)
        {
            perror("pthread_create : ");
            exit(-1);
        }
    }

    pthread_attr_destroy(&attr);
    for (int i = 0;i < len;++i)
    {
        void *tres = NULL;
        int res = pthread_join(thread[i], &tres);
        if (res != 0)
        {
            perror("pthread_join : ");
            exit(-1);
        }
        printf("thread %d joined\n",i);
    }

    return 0;
}
複製程式碼

contention scope

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

void * start(void *a)
{
    return a;
}

int main(int argc, char const *argv[])
{
    pthread_attr_t attr;
    pthread_t th;
    
    pthread_attr_init(&attr);
    /*
     scope屬性表示執行緒間競爭CPU的範圍,也就是說執行緒優先順序的有效範圍。POSIX的標準中定義了兩個值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示與系統中所有執行緒一起競爭CPU時間,後者表示僅與同程式中的執行緒競爭CPU。
     */
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
    pthread_create(&th, &attr, start, NULL);
    pthread_attr_destroy(&attr);
    
    return 0;
}
複製程式碼

lock

mutex lock

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

pthread_mutex_t mutex;
int sharedVar = 0;

void * func1(void *arg)
{
    time_t end = time(NULL) + 10;
    while(time(NULL) < end) 
    {
        int ret = pthread_mutex_trylock(&mutex);
        if(ret == EBUSY) 
        {
            printf("already lock\n");
        } 
        else if (ret == EINVAL) 
        {
            printf("lock is not init\n");
        }
        else if (ret == 0)
        {
            printf("thread 1 locked\n");
            ++sharedVar;
            pthread_mutex_unlock(&mutex);
        }
        sleep(1);
    }
    return NULL;
}

void * func2(void *arg)
{
    time_t end = time(NULL) + 10;
    while (time(NULL) < end) 
    {
        pthread_mutex_lock(&mutex);
        printf("thread 2 locked\n");
        ++sharedVar;
        sleep(1);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_mutex_init(&mutex, NULL);
    
    pthread_t th1;    
    pthread_create(&th1, NULL, func1, NULL);
    pthread_t th2;
    pthread_create(&th2, NULL, func2, NULL);
    
    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    
    pthread_mutex_destroy(&mutex);
    printf("shared var = %d\n", sharedVar);
    
    return 0;
}
複製程式碼

condition lock

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

pthread_mutex_t mutex;
pthread_cond_t cond;

typedef struct 
{
    char buff[5];
    int count;
} buffer;

buffer sharedData = {.buff = "", .count = 0};
char ch = 'A';

void * producer(void *arg)
{
    printf("producer start\n");
    
    while (ch != 'Z') 
    {
        pthread_mutex_lock(&mutex);
        
        if (sharedData.count < 5) 
        {
            sharedData.buff[sharedData.count] = ch;
            printf("producer get char %c\n", ch);
            ch++;
            sharedData.count++;
            
            if (sharedData.count == 5) 
            {
                printf("producer signal\n");
                pthread_cond_signal(&cond);
            }
        }
        
        pthread_mutex_unlock(&mutex);
    }
    
    printf("producer end\n");
    return NULL;
}

void * consumer(void *arg)
{
    printf("consumer start\n");
    
    while (ch != 'Z') 
    {
        pthread_mutex_lock(&mutex);
        
        printf("consumer wait\n");
        pthread_cond_wait(&cond, &mutex);
        
        printf("consumer write\n");
        for (int i = 0; sharedData.buff[i] && sharedData.count; ++i) 
        {
            printf("%c",sharedData.buff[i]);
            --sharedData.count;
        }
        printf("\n");
        
        pthread_mutex_unlock(&mutex);
    }
    
    printf("consumer end\n");
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    
    pthread_t cth;
    pthread_create(&cth, NULL, consumer, NULL);
    pthread_t pth;
    pthread_create(&pth, NULL, producer, NULL);
    
    pthread_join(cth, NULL);
    pthread_join(pth, NULL);
    
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    
    return 0;
} 
複製程式碼

thread storage

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

pthread_key_t key;

typedef struct 
{
    int data;
} ThreadData;

void * func(void *arg)
{
    ThreadData *data = (ThreadData *)arg;
    printf("thread %d start\n", data->data);
    pthread_setspecific(key,data);
    printf("thread data is %d\n", ((ThreadData *)pthread_getspecific(key))->data);
    printf("thread %d exit\n", data->data);
    return arg;
}

void deconstruct(void *arg)
{
    printf("thread %d data free\n", ((ThreadData *)arg)->data);
    free(arg);
}

int main(int argc, char *argv[])
{
    pthread_t thread[5];
    size_t len = sizeof(thread)/sizeof(pthread_t);
    pthread_key_create(&key,deconstruct);
    
    for (int i = 0; i < len; ++i) 
    {
        ThreadData *threadData = (ThreadData *)malloc(sizeof(ThreadData));
        threadData->data = i;
        pthread_create(&thread[i], NULL, func, threadData);
    }
    
    for (int i = 0; i < len; ++i)
    {
        pthread_join(thread[i], NULL);
    }
    
    pthread_key_delete(key);
    return 0;
}
複製程式碼

相關文章