這裏主要演示線程的以下幾個特性
- 線程共享同一地址空間(全局變量,堆,棧)
- 線程退出引起進程退出
- 多線程充分利用多核CPU資源
同組線程共用同一地址空間
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//1.共享全局區資源
int g_count = 0;
void* ThreadEntry1(void* arg)
{
(void)arg;
while(1)
{
++g_count;
printf("t1 : %d\n",g_count);
sleep(1);
}
return NULL;
}
void* ThreadEntry2(void* arg)
{
(void)arg;
while(1)
{
++g_count;
printf("t2 : %d\n",g_count);
sleep(1);
}
return NULL;
}
int main()
{
pthread_t t1,t2;
pthread_create(&t1,NULL,ThreadEntry1,NULL);
pthread_create(&t2,NULL,ThreadEntry2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
上面代碼中,有一個全局變量 g_count,兩個線程,同時嘗試去對 全局變量 g_count 進行修改
結果演示:
根據運行結果,我們可以看到,同組線程對全局變量是共享的
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//2.共享堆上的資源
void* ThreadEntry1(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t1 : %d\n",*p);
sleep(1);
}
return NULL;
}
void* ThreadEntry2(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t2 : %d\n",*p);
sleep(1);
}
return NULL;
}
int main()
{
int* p = (int*)malloc(sizeof(int));
pthread_t t1,t2;
pthread_create(&t1,NULL,ThreadEntry1,p);
pthread_create(&t2,NULL,ThreadEntry2,p);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
上面代碼中,在main函數中malloc出了一段空間,這段空間在堆上,線程1和2同時去修改這個堆上的變量。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//3.共享線程棧
// 使用棧上變量比較危險,我們使用前必須保證變量存在
// 但是主線程比較安全,因爲他存在於整個進程
void* ThreadEntry1(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t1 : %d\n",*p);
sleep(1);
}
return NULL;
}
void* ThreadEntry2(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t2 : %d\n",*p);
sleep(1);
}
return NULL;
}
int main()
{
int a = 0;
int* p = &a;
pthread_t t1,t2;
pthread_create(&t1,NULL,ThreadEntry1,p);
pthread_create(&t2,NULL,ThreadEntry2,p);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
代碼中將主線程棧上一個變量a傳給兩個線程的線程入口函數,線程1和2分別隨主線程棧上的元素進行改變。
注意:
修改棧上的資源是比較危險的,因爲我們說過,每個線程都有自己的一個棧,這個但是這個棧是可以被訪問也可以被改變的,試想,如果線程1已經退出了,線程2嘗試去修改線程1棧上的元素,這是就很可能造成訪問越界!但是,訪問主線程棧上的元素相對比較安全,因爲主線程棧是大家所共享的。
線程退出引起進程退出
線程組中某一個線程訪存異常,都會導致進程異常終止。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//解引用空指針
//會導致硬件設備MMU發現這是一個異常操作
//會給操作系統發送一個異常
//操作系統內核就會給進程發送11號信號,導致進程異常終止 - 段錯誤
//解引用空指針使線程異常終止,觀察
//線程一旦異常終止,就會導致整個進程都結束掉
void* ThreadEntry1(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t1 : %d\n",*p);
int *ptr = NULL;
*ptr = 10;
sleep(1);
}
return NULL;
}
void* ThreadEntry2(void* arg)
{
int* p = (int*)arg;
while(1)
{
++(*p);
printf("t2 : %d\n",*p);
sleep(1);
}
return NULL;
}
int main()
{
int a = 0;
int* p = &a;
pthread_t t1,t2;
pthread_create(&t1,NULL,ThreadEntry1,p);
pthread_create(&t2,NULL,ThreadEntry2,p);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
線程嘗試對空指針解引用時,進程終止。
多線程充分利用多核CPU資源
- 場景1,創建對個線程不停歇工作,使用top指令查看CPU利用率
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//利用top指令查看cpu佔用率
void* ThreadEntry(void* arg)
{
(void)arg;
while(1)
{}
return NULL;
}
int main()
{
pthread_t tid[32];
int n = 4;
int i = 0;
for(; i < n; ++i)
{
pthread_create(&tid[i],NULL,ThreadEntry,NULL);
}
for(i = 0; i < n; ++i)
{
pthread_join(tid[i],NULL);
}
return 0;
}