學習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;
}
複製程式碼