首頁 運維 linux運維 Linux多線程程式設計實例程式碼分析

Linux多線程程式設計實例程式碼分析

May 26, 2023 pm 10:04 PM
linux

下面先來一個實例。我們透過建立兩個執行緒來實現一個數的遞加。或許這個實例沒有實際運用的價值,但是稍微改動一下,我們就可以用到其他地方去拉。

程式碼:

/*thread_example.c : c multiple thread programming in linux
 *author : falcon
 *e-mail : tunzhj03@st.lzu.edu.cn
 */
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define max 10

pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;

void *thread1()
{
    printf ("thread1 : i&#39;m thread 1/n");

    for (i = 0; i < max; i++)
    {
        printf("thread1 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(2);
    }


    printf("thread1 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void *thread2()
{
    printf("thread2 : i&#39;m thread 2/n");

    for (i = 0; i < max; i++)
    {
        printf("thread2 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(3);
    }


    printf("thread2 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void thread_create(void)
{
    int temp;
    memset(&thread, 0, sizeof(thread));     //comment1
    /*创建线程*/
    if((temp = pthread_create(&thread[0], null, thread1, null)) != 0) //comment2   
        printf("线程1创建失败!/n");
    else
        printf("线程1被创建/n");

    if((temp = pthread_create(&thread[1], null, thread2, null)) != 0) //comment3
        printf("线程2创建失败");
    else
        printf("线程2被创建/n");
}

void thread_wait(void)
{
    /*等待线程结束*/
    if(thread[0] !=0)      {       //comment4          pthread_join(thread[0],null);
        printf("线程1已经结束/n");
     }
    if(thread[1] !=0)      {         //comment5        pthread_join(thread[1],null);
        printf("线程2已经结束/n");
     }
}

int main()
{
    /*用默认属性初始化互斥锁*/
    pthread_mutex_init(&mut,null);

    printf("我是主函数哦,我正在创建线程,呵呵/n");
    thread_create();
    printf("我是主函数哦,我正在等待线程完成任务阿,呵呵/n");
    thread_wait();

    return 0;
}
登入後複製

下面我們先來編譯、執行一下

#引文:

falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/c/code/ftp$ ./thread_example
我是主函数哦,我正在创建线程,呵呵
线程1被创建
线程2被创建
我是主函数哦,我正在等待线程完成任务阿,呵呵
thread1 : i&#39;m thread 1
thread1 : number = 0
thread2 : i&#39;m thread 2
thread2 : number = 1
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
thread1 : number = 6
thread1 : number = 7
thread2 : number = 8
thread1 : number = 9
thread2 : number = 10
thread1 :主函数在等我完成任务吗?
线程1已经结束
thread2 :主函数在等我完成任务吗?
线程2已经结束
登入後複製

實例程式碼裡頭的註解應該比較清楚了吧,下面我把網路上介紹上面牽涉到的幾個函數和變數給引用過來。

引文:

執行緒相關操作

一pthread_t

pthread_t在頭檔/usr/include/bits/pthreadtypes.h中定義:
  typedef unsigned long int pthread_t;
  它是一個執行緒的識別碼。

二pthread_create

函數pthread_create用來建立一個線程,它的原型是:
  extern int pthread_create __p ((pthread_t *__thread, __const _attr_t*__ (*__start_routine) (void *), void *__arg));
  第一個參數為指向線程標識符的指針,第二個參數用來設定線程屬性,第三個參數是線程運行函數的起始地址,最後一個參數是運行函數的參數。這裡,我們的函數thread不需要參數,所以最後一個參數設為空指標。第二個參數我們也設為空指針,這樣會產生預設屬性的線程。線程屬性的設定和修改我們將在下一節闡述。當建立線程成功時,函數傳回0,若不為0則表示建立線程失敗,常見的錯誤回傳代碼為eagain和einval。前者表示系統限制創建新的線程,例如線程數目過多了;後者表示第二個參數代表的線程屬性值非法。建立執行緒成功後,新建立的執行緒則執行參數三和參數四確定的函數,原來的執行緒繼續執行下一行程式碼。

三 pthread_join pthread_exit

  
函數pthread_join用來等待一個執行緒的結束。函數原型為:
  extern int pthread_join __p ((pthread_t __th, void **__thread_return));
  第一個參數為被等待的執行緒標識符,第二個參數為一個使用者定義的指針,它可以用來儲存被等待線程的回傳值。這個函數是一個執行緒阻塞的函數,呼叫它的函數會一直等待到被等待的執行緒結束為止,當函數回傳時,被等待執行緒的資源被收回。一個執行緒的結束有兩種途徑,一種是像我們上面的例子一樣,函數結束了,呼叫它的執行緒也就結束了;另一種方式是透過函數pthread_exit來實現。它的函數原型為:
  extern void pthread_exit __p ((void *__retval)) __attribute__ ((__noreturn__));
  唯一的參數是函數的回傳碼,只要pthread_join中的第二個參數,這個值將會被傳遞給thread_return。最後要說明的是,一個執行緒不能被多個執行緒等待,否則第一個接收到訊號的執行緒成功返回,其餘呼叫pthread_join的執行緒則傳回錯誤代碼esrch。
  在這一節裡,我們寫了一個最簡單的線程,並掌握了最常用的三個函數pthread_create,pthread_join和pthread_exit。下面,我們來了解線程的一些常用屬性以及如何設定這些屬性。

互斥鎖相關

互斥鎖用來保證一段時間內只有一個執行緒在執行一段程式碼。

一 pthread_mutex_init

函數pthread_mutex_init用來產生一個互斥鎖。 null參數表示使用預設屬性。如果需要宣告特定屬性的互斥鎖,須呼叫函數 pthread_mutexattr_init。函數pthread_mutexattr_setpshared和函數 pthread_mutexattr_settype用來設定互斥鎖屬性。前一個函數設定屬性pshared,它有兩個取值, pthread_process_private和pthread_process_shared。前者用來不同行程中的執行緒同步,後者用於同步本行程的不同執行緒。在上面的範例中,我們使用的是預設屬性pthread_process_ private。後者用來設定互斥鎖類型,可選的類型有pthread_mutex_normal、pthread_mutex_errorcheck、 pthread_mutex_recursive和pthread _mutex_default。它們分別定義了不同的上所、解鎖機制,一般情況下,選用最後一個預設屬性。

二 pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

   pthread_mutex_lock聲明開始用互斥鎖上鎖,此後的程式碼直到呼叫pthread_mutex_unlock為止,都被上鎖,即同一時間只能被一個執行緒執行。當一個執行緒執行到pthread_mutex_lock處時,如果該鎖定此時被另一個執行緒使用,那麼此執行緒被阻塞,即程式將等待到另一個執行緒釋放此互斥鎖。

注意:

1 需要說明的是,上面的兩處sleep不光是為了演示的需要,也是為了讓線程睡眠一段時間,讓線程釋放互斥鎖,等待另一個線程使用此鎖。下面的參考資料1裡頭說明了這個問題。但在linux下好像沒有pthread_delay_np那個函數(我試了一下,提示沒有定義該函數的引用),所以我用了sleep來代替,不過參考資料2中給出另一種方法,好像是透過pthread_cond_timedwait來代替,裡頭給了一種實現的辦法。

2 請千萬要注意裡頭的註解comment1-5,那是我花了幾個小時才找出的問題所在。
如果沒有comment1和comment4,comment5,將導致在pthread_join的時候出現段錯誤,另外,上面的comment2和comment3是根源所在,所以千萬要記得寫全代碼。因為上面的線程可能沒有創建成功,導致下面不可能等到那個線程結束,而在用pthread_join的時候出現段錯誤(訪問了未知的內存區)。另外,使用memset的時候,需要包含string.h頭檔哦

以上是Linux多線程程式設計實例程式碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

在Linux終端中使用python --version命令時如何解決權限問題? 在Linux終端中使用python --version命令時如何解決權限問題? Apr 02, 2025 am 06:36 AM

Linux終端中使用python...

c語言多線程的四種實現方式 c語言多線程的四種實現方式 Apr 03, 2025 pm 03:00 PM

語言多線程可以大大提升程序效率,C 語言中多線程的實現方式主要有四種:創建獨立進程:創建多個獨立運行的進程,每個進程擁有自己的內存空間。偽多線程:在一個進程中創建多個執行流,這些執行流共享同一內存空間,並交替執行。多線程庫:使用pthreads等多線程庫創建和管理線程,提供了豐富的線程操作函數。協程:一種輕量級的多線程實現,將任務劃分成小的子任務,輪流執行。

web.xml怎麼打開 web.xml怎麼打開 Apr 03, 2025 am 06:51 AM

要打開 web.xml 文件,可以使用以下方法:使用文本編輯器(如記事本或 TextEdit)使用集成開發環境(如 Eclipse 或 NetBeans)使用命令行編輯命令(Windows:notepad web.xml;Mac/Linux:open -a TextEdit web.xml)

Linux系統自帶Python解釋器能刪除嗎? Linux系統自帶Python解釋器能刪除嗎? Apr 02, 2025 am 07:00 AM

關於Linux系統自帶Python解釋器的刪除問題許多Linux發行版在安裝時會預裝Python解釋器,它並非通過軟件包管理器�...

Linux最好使用的是什麼? Linux最好使用的是什麼? Apr 03, 2025 am 12:11 AM

Linux最適合用作服務器管理、嵌入式系統和桌面環境。 1)在服務器管理中,Linux用於託管網站、數據庫和應用程序,提供穩定性和可靠性。 2)在嵌入式系統中,Linux因其靈活性和穩定性被廣泛應用於智能家居和汽車電子系統。 3)在桌面環境中,Linux提供了豐富的應用和高效的性能。

Debian Hadoop 兼容性怎樣 Debian Hadoop 兼容性怎樣 Apr 02, 2025 am 08:42 AM

DebianLinux以其稳定性和安全性著称,广泛应用于服务器、开发和桌面环境。虽然目前缺乏关于Debian与Hadoop直接兼容性的官方说明,但本文将指导您如何在Debian系统上部署Hadoop。Debian系统需求:在开始Hadoop配置前,请确保您的Debian系统满足Hadoop的最低运行要求,这包括安装必要的Java运行时环境(JRE)和Hadoop软件包。Hadoop部署步骤:下载并解压Hadoop:从ApacheHadoop官方网站下载您需要的Hadoop版本,并将其解

使用Go語言連接Oracle數據庫時是否需要安裝Oracle客戶端? 使用Go語言連接Oracle數據庫時是否需要安裝Oracle客戶端? Apr 02, 2025 pm 03:48 PM

使用Go語言連接Oracle數據庫時是否需要安裝Oracle客戶端?在使用Go語言開發時,連接Oracle數據庫是一個常見需求�...

Debian Strings能否兼容多種瀏覽器 Debian Strings能否兼容多種瀏覽器 Apr 02, 2025 am 08:30 AM

“DebianStrings”並非標準術語,其具體含義尚不明確。本文無法直接評論其瀏覽器兼容性。然而,如果“DebianStrings”指的是在Debian系統上運行的Web應用,則其瀏覽器兼容性取決於應用本身的技術架構。大多數現代Web應用都致力於跨瀏覽器兼容性。這依賴於遵循Web標準,並使用兼容性良好的前端技術(如HTML、CSS、JavaScript)以及後端技術(如PHP、Python、Node.js等)。為了確保應用與多種瀏覽器兼容,開發者通常需要進行跨瀏覽器測試,並使用響應式

See all articles