新聞中心
Linux是目前最為流行的操作系統(tǒng)之一,它的強大之處在于其開放性和靈活性。作為一名Linux開發(fā)者或者系統(tǒng)管理員,深入了解Linux線程是非常重要的一步。

本文將通過實例來幫助讀者掌握Linux線程的基本知識。我們將使用C語言和Linux的pthread庫來創(chuàng)建、管理和控制線程,并介紹一些基本的線程概念和技術(shù)。
為了更好地理解本文中的示例代碼,我們假設(shè)讀者已經(jīng)了解C語言基礎(chǔ)和Linux基礎(chǔ)知識,并熟悉使用Linux的命令行界面。
一、線程基礎(chǔ)概念
在開始講解Linux線程之前,我們先了解一些基本概念。
線程是計算機操作系統(tǒng)中的一個執(zhí)行單位,它是作系統(tǒng)獨立調(diào)度和管理的最小運行單位。一個進程可以包含多個線程,多個線程可以同時執(zhí)行,并共享進程的資源。
與進程不同,線程之間共享了進程的資源(堆、全局變量、靜態(tài)變量等),因此線程間的通信也更加方便。此外,線程的創(chuàng)建和銷毀比進程更加輕量級和快速。因此,線程在多任務(wù)操作中有著重要的應(yīng)用。
二、線程的創(chuàng)建和銷毀
接下來我們通過一個簡單的例子來創(chuàng)建和銷毀線程。
#include
#include
#include
void *hello_thread(void *arg)
{
int i;
for (i = 0; i
{
printf(“hello thread!\n”);
sleep(1);
}
return NULL;
}
int mn(int argc, char *argv[])
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, hello_thread, NULL);
if (ret != 0)
{
printf(“pthread_create error:ret=%d\n”, ret);
return -1;
}
printf(“create thread %lu\n”, tid);
pthread_join(tid, NULL);
return 0;
}
上述代碼中,我們首先定義了一個hello_thread函數(shù),用于線程執(zhí)行的任務(wù)。接著,我們在mn函數(shù)中使用pthread_create函數(shù)創(chuàng)建了一個新的線程,傳入線程ID、線程屬性、線程函數(shù)以及傳遞給線程函數(shù)的參數(shù)。線程創(chuàng)建成功后,主線程會打印出創(chuàng)建的線程ID。我們使用pthread_join函數(shù)等待線程的結(jié)束。
你可以使用gcc編譯該代碼,如下所示:
$ gcc -o thread thread.c -lpthread
執(zhí)行編譯后的可執(zhí)行文件,你將看到如下輸出:
create thread 3079033696
hello thread!
hello thread!
hello thread!
上述示例中,我們調(diào)用了pthread_create函數(shù)來創(chuàng)建一個線程。pthread_create函數(shù)的之一個參數(shù)傳入要創(chuàng)建的線程ID,第二個參數(shù)指定線程的屬性(通常為NULL),第三個參數(shù)是線程函數(shù)的指針(函數(shù)名不需加括號),最后一個參數(shù)是傳遞給線程函數(shù)的參數(shù)(通常為NULL)。
線程創(chuàng)建成功后,主線程繼續(xù)執(zhí)行,而新線程開始執(zhí)行其指定的函數(shù)。在我們的示例中,新線程是輸出”hello thread!” 三次,每次隔1秒鐘,然后退出。當(dāng)線程函數(shù)返回NULL時,表示線程任務(wù)結(jié)束。主線程調(diào)用pthread_join等待子線程完成。
三、線程同步
在多線程編程中,線程同步是非常重要的概念。特別是在共享資源的情況下,要確保線程的正確性和一致性。
我們以生產(chǎn)者消費者為例,講述如何使用線程同步來確保數(shù)據(jù)的正確性。這里我們假設(shè)有一個環(huán)形緩沖區(qū),它被一個單獨的線程用于生產(chǎn)數(shù)據(jù),一個線程用于消費數(shù)據(jù)。生產(chǎn)者在存儲數(shù)據(jù)時會檢查環(huán)形緩沖區(qū)是否已滿,消費者在取出數(shù)據(jù)時會檢查緩沖區(qū)是否為空。
我們使用兩個互斥鎖(pthread_mutex_t)和兩個條件變量(pthread_cond_t)來實現(xiàn)上述場景。
#include
#include
#include
#define BUFFER_SIZE 4
int buffer[BUFFER_SIZE];
int g_write_idx = 0;
int g_read_idx = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_notempty_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t g_notfull_cond = PTHREAD_COND_INITIALIZER;
void *producer_thread(void *arg)
{
int i;
for (i = 0; i
{
pthread_mutex_lock(&g_mutex);
while (g_write_idx == BUFFER_SIZE)
{
pthread_cond_wt(&g_notfull_cond, &g_mutex);
}
buffer[g_write_idx++] = i;
printf(“produce: %d\n”, i);
pthread_cond_signal(&g_notempty_cond);
pthread_mutex_unlock(&g_mutex);
}
return NULL;
}
void *consumer_thread(void *arg)
{
int i, data;
for (i = 0; i
{
pthread_mutex_lock(&g_mutex);
while (g_write_idx == 0)
{
pthread_cond_wt(&g_notempty_cond, &g_mutex);
}
data = buffer[g_read_idx++];
printf(“consume: %d\n”, data);
pthread_cond_signal(&g_notfull_cond);
pthread_mutex_unlock(&g_mutex);
}
return NULL;
}
int mn(int argc, char *argv[])
{
pthread_t producer_tid, consumer_tid;
pthread_create(&producer_tid, NULL, producer_thread, NULL);
pthread_create(&consumer_tid, NULL, consumer_thread, NULL);
pthread_join(producer_tid, NULL);
pthread_join(consumer_tid, NULL);
return 0;
}
上述代碼中,我們首先定義BUFFER_SIZE表示緩沖區(qū)的大小,然后定義g_write_idx和g_read_idx分別表示寫下標(biāo)和讀下標(biāo)。接著我們定義了兩個互斥鎖g_mutex和兩個條件變量g_notempty_cond和g_notfull_cond。
在生產(chǎn)者線程中,我們使用pthread_mutex_lock函數(shù)來訪問共享資源buffer和g_write_idx,如果發(fā)現(xiàn)緩沖區(qū)已滿,線程將使用pthread_cond_wt函數(shù)等待g_notfull_cond條件變量。當(dāng)消費者取出數(shù)據(jù)后,生產(chǎn)者線程將使用pthread_cond_signal函數(shù)通知消費者線程緩沖區(qū)中已經(jīng)有可讀數(shù)據(jù),然后釋放互斥鎖。
在消費者線程中,我們也使用pthread_mutex_lock函數(shù)來訪問共享資源buffer和g_read_idx,如果發(fā)現(xiàn)緩沖區(qū)為空,線程將使用pthread_cond_wt函數(shù)等待g_notempty_cond條件變量。當(dāng)生產(chǎn)者存儲了新數(shù)據(jù)后,消費者線程將使用pthread_cond_signal函數(shù)通知生產(chǎn)者線程緩沖區(qū)中已經(jīng)有空閑空間,然后釋放互斥鎖。
在主函數(shù)中,我們調(diào)用pthread_create函數(shù)來創(chuàng)建生產(chǎn)者線程和消費者線程,并使用pthread_join等待兩個線程結(jié)束。
四、線程池
線程池是一種常見的多線程技術(shù),它可以在應(yīng)用程序中管理和調(diào)度大量線程。線程池中的線程通常是預(yù)先創(chuàng)建好的,它們將等待任務(wù)的到來并處理任務(wù)。使用線程池可以避免線程頻繁創(chuàng)建和銷毀的開銷,提高多線程的效率。
下面我們介紹如何使用線程池來執(zhí)行一個簡單的任務(wù)。
#include
#include
#include
#include
#include
#define DEFAULT_THREAD_NUM 3
typedef struct task_s
{
void *(*task_func)(void *);
void *arg;
struct task_s *next;
} task_t;
typedef struct threadpool_s
{
int thread_num;
pthread_t *threads;
pthread_mutex_t lock;
pthread_cond_t cond;
task_t *head;
task_t *tl;
int shutdown;
} threadpool_t;
void *threadpool_worker(void *arg)
{
threadpool_t *pool = (threadpool_t *)arg;
task_t *task = NULL;
while (1)
{
pthread_mutex_lock(&pool->lock);
while (!pool->shutdown && !pool->head)
{
pthread_cond_wt(&pool->cond, &pool->lock);
}
if (pool->shutdown)
{
pthread_mutex_unlock(&pool->lock);
pthread_exit(NULL);
}
task = pool->head;
pool->head = task->next;
if (pool->head == NULL)
{
pool->tl = NULL;
}
pthread_mutex_unlock(&pool->lock);
printf(“Do something…\n”);
task->task_func(task->arg);
free(task);
}
return NULL;
}
int threadpool_create(threadpool_t *pool, int thread_num)
{
int i;
pool->thread_num = thread_num;
pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * thread_num);
if (pool->threads == NULL)
{
perror(“malloc”);
return -1;
}
pool->head = NULL;
pool->tl = NULL;
if (pthread_mutex_init(&pool->lock, NULL) != 0)
{
perror(“pthread_mutex_init”);
return -1;
}
if (pthread_cond_init(&pool->cond, NULL) != 0)
{
perror(“pthread_cond_init”);
return -1;
}
pool->shutdown = 0;
for (i = 0; i
{
if (pthread_create(&pool->threads[i], NULL, threadpool_worker, (void *)pool) != 0)
{
perror(“pthread_create”);
return -1;
}
}
return 0;
}
void threadpool_destroy(threadpool_t *pool)
{
int i;
task_t *task;
if (pool->shutdown)
{
return;
}
pool->shutdown = 1;
pthread_cond_broadcast(&pool->cond);
for (i = 0; i thread_num; i++)
{
pthread_join(pool->threads[i], NULL);
}
free(pool->threads);
while (pool->head)
{
task = pool->head;
pool->head = task->next;
free(task);
}
pool->head = NULL;
pool->tl = NULL;
pthread_mutex_destroy(&pool->lock);
pthread_cond_destroy(&pool->cond);
}
int threadpool_add_task(threadpool_t *pool, void *(*task_func)(void *), void *arg)
{
task_t *task = (task_t *)malloc(sizeof(task_t));
if (task == NULL)
{
return -1;
}
task->next = NULL;
task->task_func = task_func;
task->arg = arg;
pthread_mutex_lock(&pool->lock);
if (pool->tl == NULL)
{
pool->head = task;
pool->tl = task;
}
else
{
pool->tl->next = task;
pool->tl = task;
}
pthread_cond_signal(&pool->cond);
pthread_mutex_unlock(&pool->lock);
return 0;
}
void *task_func(void *arg)
{
char *str = (char *)arg;
sleep(1);
printf(“Task is doing (%s)…\n”, str);
return NULL;
}
int mn(int argc, const char *argv[])
{
int i;
threadpool_t pool;
if (threadpool_create(&pool, DEFAULT_THREAD_NUM) != 0)
{
perror(“threadpool_create”);
return -1;
}
for (i = 0; i
{
char str[128] = {0};
sprintf(str, “task_%d”, i);
threadpool_add_task(&pool, task_func, strdup(str));
}
sleep(5);
threadpool_destroy(&pool);
return 0;
}
上述代碼中,我們首先定義了一個task_t結(jié)構(gòu)體,表示任務(wù)的數(shù)據(jù)結(jié)構(gòu)。然后定義了一個threadpool_t結(jié)構(gòu)體,表示線程池的數(shù)據(jù)結(jié)構(gòu)。
在線程池的創(chuàng)建函數(shù)threadpool_create中,我們首先動態(tài)分配了線程數(shù)組,然后初始化了線程池的鎖和條件變量。接著,我們使用pthread_create函數(shù)創(chuàng)建了指定數(shù)量的工作線程,并在這些線程中不斷從線程池中取出任務(wù)進行處理。
在線程池的銷毀函數(shù)threadpool_destroy中,我們首先通知所有工作線程退出,然后等待所有線程并成功退出。我們釋放線程數(shù)組和任務(wù)隊列中的所有任務(wù),銷毀線程池的鎖和條件變量。
在向線程池添加任務(wù)時,我們創(chuàng)建一個新的任務(wù)并加入到線程池的任務(wù)隊列中。這里我們使用了pthread_mutex_lock和pthread_cond_signal函數(shù)來保證多個線程都正確地訪問任務(wù)隊列。
在任務(wù)的執(zhí)行函數(shù)task_func中,我們僅僅是簡單地休眠了一秒鐘,然后輸出一個字符串。
在主函數(shù)中,我們使用threadpool_create函數(shù)來創(chuàng)建線程池并向線程池中加入了10個需要執(zhí)行的任務(wù),然后等待5秒鐘后,使用threadpool_destroy函數(shù)銷毀線程池。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián),建站經(jīng)驗豐富以策略為先導(dǎo)10多年以來專注數(shù)字化網(wǎng)站建設(shè),提供企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計,響應(yīng)式網(wǎng)站制作,設(shè)計師量身打造品牌風(fēng)格,熱線:028-86922220關(guān)于嵌入式linux系統(tǒng)的問題,多線程,基于arm9開發(fā)板
1)
linux二進制可執(zhí)行文件是無法得轉(zhuǎn)換為代碼的,所以修改不了代碼,只能找源碼去改,改完了重新交叉編譯再寫進開發(fā)板上。
2)
使用linux多線程問題模姿燃,A中滿足條件創(chuàng)建線程B,線程B中滿足條件創(chuàng)建線程C,如果你線程A和B沒有退出,A和B都會繼續(xù)執(zhí)行
實例程序如下:main中十秒后創(chuàng)建線程A ,A中10秒后創(chuàng)建B,B線程十秒后創(chuàng)建線程C,每個線程中都會有打印信息,當(dāng)出現(xiàn)pthread A pthread B pthread C同時出現(xiàn)時,證明三個線程同時存活
此程序編譯時需加-phread參數(shù),例如:cc pthread_join.c -pthread
#include
#include
#include
#include
#include
void * A();//線程函數(shù)聲明
void * B();
void * C();
void * A()
{
pthread_t b;
int i = 0;
while(i
{
if (++i == 10)
pthread_create(&b, NULL, (void *)B, NULL );//創(chuàng)建線程B
sleep(1);
printf(“pthread A\n”);
}
pthread_join(b, NULL);
return 0;
}
void * B()
{
pthread_t c;
int i = 0;
while(i
{
if (++i == 10)
pthread_create(&c, NULL, (void *)C, NULL );/冊晌/創(chuàng)建線程C
printf(“pthread B\n”);
sleep(1);
}
pthread_join(c, NULL);
return 0;
}
void *C()
{
int i = 0;
while(i
{
printf(“pthread C\n”);
sleep(1);
i++;
}
return 0;
}
int main()
{
pthread_t a;
int i = 0;
while(i
{
if (++i == 10)
pthread_create(&a, NULL, (void *)A, NULL );//創(chuàng)建線程A
printf(“i = %d\n”, i );
sleep(1);
}
pthread_join(a, NULL);
return 0;
}
以上是多線程程序的例子
但是,如果你想一個程序調(diào)用另一個程序時,你可以這樣做:
比如你有三個可執(zhí)行程序a.out b.out c.out
運行a.out當(dāng)符合某個程旦虛序時使用system(“./b.out”);調(diào)用程序b.out,在b.out程序中以同樣的方法調(diào)用程序c.out。但此時已經(jīng)不是多線程了,而是三個不同的進程,進程a.out b.out 和c.out
也可以在上面的程序中十秒的時候創(chuàng)建子進程后,在子進程中以system(“./b.out”);來運行程序b.out
linux下多線程編程問題,求各種優(yōu)化
while((p=fork())==-1);//創(chuàng)建進程
if(p==0)
{
ret=pthread_create(&id1,NULL,(void *)pthread1, NULL);//創(chuàng)建線程
if(ret!=0) perror(“線程1創(chuàng)建失敗”);
ret=pthread_create(&id2,NULL,(void *)pthread2, NULL);
if(ret!=0) perror(“線程2創(chuàng)建失敗”);
ret=pthread_create(&id3,NULL,(void *)pthread3, NULL);
if(ret!=0) perror(“線程3創(chuàng)建失敗”);
……
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_join(id3,NULL);
………./缺搭侍/結(jié)束線程
exit(0);
}
void pthread1(void *arg)
{
while(time(NULL)
{
if(pthread_mutex_lock(&mutex)!=0)//鎖定數(shù)據(jù) 可以在這里判斷接入次數(shù),現(xiàn)在是寫鎖定判斷
{
perror(“鎖定失敗”);
}
else printf(“線程1:鎖定數(shù)據(jù)量\n”);
{
}
if(pthread_mutex_unlock(&mutex)!=0) //數(shù)據(jù)解鎖 這里可以判斷不超過3次鎖定解鎖
{
perror(“解鎖失敗”);
}
else
printf(“線程1:我已解鎖\n”);
sleep(4);
}
}
其他的你自己補充吧,自己定義幾個全局變伏吵量控制線程鎖定解鎖邏輯關(guān)系就行
點擊我百度名字,進入尋找真相在內(nèi),相信你懂的
線程太頭疼,鎖賴鎖去會死人的
linux 線程中,線程宿主函數(shù)是什么意思?宿體函數(shù)又是什么意思?二者有什么區(qū)別?更好能舉個例子。
宿主函數(shù)是你調(diào)用建立線程的函數(shù),而宿體函數(shù)是你線程運行起來后執(zhí)行的函數(shù)
void f(void *arg);
void ff()
{
/弊逗*…*/
pthread_creat(…., …, f, NULL);
}
上面租舉賣例子中ff是宿主,f是宿答臘體
linux thread 例子的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux thread 例子,學(xué)習(xí)Linux線程:通過實例掌握基本知識,關(guān)于嵌入式linux系統(tǒng)的問題,多線程,基于arm9開發(fā)板,linux下多線程編程問題,求各種優(yōu)化,linux 線程中,線程宿主函數(shù)是什么意思?宿體函數(shù)又是什么意思?二者有什么區(qū)別?更好能舉個例子。的信息別忘了在本站進行查找喔。
創(chuàng)新互聯(lián)【028-86922220】值得信賴的成都網(wǎng)站建設(shè)公司。多年持續(xù)為眾多企業(yè)提供成都網(wǎng)站建設(shè),成都品牌建站設(shè)計,成都高端網(wǎng)站制作開發(fā),SEO優(yōu)化排名推廣服務(wù),全網(wǎng)營銷讓企業(yè)網(wǎng)站產(chǎn)生價值。
文章標(biāo)題:學(xué)習(xí)Linux線程:通過實例掌握基本知識(linuxthread例子)
本文URL:http://m.fisionsoft.com.cn/article/cdgegoh.html


咨詢
建站咨詢
