青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 40, 文章 - 0, 評論 - 9, 引用 - 0
數據加載中……

Linux下多線程編程詳解

http://www.yuanma.org/data/2007/0921/article_2859.htm

線程(thread)技術早在60年代就被提出,但真正應用多線程到操作系統中去,是在80年代中期,solaris是這方面的佼佼者。傳統的Unix也支持線程的概念,但是在一個進程(process)中只允許有一個線程,這樣多線程就意味著多進程。
現在,多線程技術已經被許多操作系統所支持,包括Windows/NT,當然,也包括Linux。

  為什么有了進程的概念后,還要再引入線程呢?使用多線程到底有哪些好處?什么的系統應該選用多線程?我們首先必須回答這些問題。

使用多線程的理由之一是和進程相比,它是一種非常"節儉"的多任務操作方式。我們知道,在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空 間,建立眾多的數據表來維護它的代碼段、堆棧段和數據段,這是一種"昂貴"的多任務工作方式。而運行于一個進程中的多個線程,它們彼此之間使用相同的地址 空間,共享大部分數據,啟動一個線程所花費的空間遠遠小于啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小于進程間切換所需要的時間。 據統計,總的說來,一個進程的開銷大約是一個線程開銷的30倍左右,當然,在具體的系統上,這個數據可能會有較大的區別。

  使用多線程 的理由之二是線程間方便的通信機制。對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方 便。線程則不然,由于同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其它線程所用,這不僅快捷,而且方便。當然,數據的共享也帶來其他 一些問題,有的變量不能同時被兩個線程所修改,有的子程序中聲明為static的數據更有可能給多線程程序帶來災難性的打擊,這些正是編寫多線程程序時最 需要注意的地方。

  除了以上所說的優點外,不和進程比較,多線程程序作為一種多任務、并發的工作方式,當然有以下的優點:

  1) 提高應用程序響應。這對圖形界面的程序尤其有意義,當一個操作耗時很長時,整個系統都會等待這個操作,此時程序不會響應鍵盤、鼠標、菜單的操作,而使用多線程技術,將耗時長的操作(time consuming)置于一個新的線程,可以避免這種尷尬的情況。

  2) 使多CPU系統更加有效。操作系統會保證當線程數不大于CPU數目時,不同的線程運行于不同的CPU上。

  3) 改善程序結構。一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。

  下面我們先來嘗試編寫一個簡單的多線程程序。

  簡單的多線程編程

Linux系統下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時需要 使用庫libpthread.a。順便說一下,Linux下pthread的實現是通過系統調用clone()來實現的。clone()是Linux所特 有的系統調用,它的使用方式類似fork,關于clone()的詳細情況,有興趣的讀者可以去查看有關文檔說明。下面我們展示一個最簡單的多線程程序 pthread_create.c。


一個重要的線程創建函數原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

    返回值:若是成功建立線程返回0,否則返回錯誤的編號
    形式參數:
                pthread_t *restrict tidp 要創建的線程的線程id指針
                const pthread_attr_t *restrict attr 創建線程時的線程屬性
                void* (start_rtn)(void) 返回值是void類型的指針函數
                void *restrict arg   start_rtn的行參
                
例程1:                               
    功能:創建一個簡單的線程
    程序名稱:pthread_create.c         
/********************************************************************************************
**    Name:pthread_create.c
**    Used to study the multithread programming in Linux OS
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *myThread1(void)
{
    int i;
    for (i=0; i<100; i++)
    {
        printf("This is the 1st pthread,created by zieckey.\n");
        sleep(1);//Let this thread to sleep 1 second,and then continue to run
    }
}

void *myThread2(void)
{
    int i;
    for (i=0; i<100; i++)
    {
        printf("This is the 2st pthread,created by zieckey.\n");
        sleep(1);
    }
}

int main()
{
    int i=0, ret=0;
    pthread_t id1,id2;
   
    ret = pthread_create(&id2, NULL, (void*)myThread1, NULL);
    if (ret)
    {
        printf("Create pthread error!\n");
        return 1;
    }
   
    ret = pthread_create(&id2, NULL, (void*)myThread2, NULL);
    if (ret)
    {
        printf("Create pthread error!\n");
        return 1;
    }
   
    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
   
    return 0;
}


  我們編譯此程序:
# gcc pthread_create.c -lpthread

因為pthread的庫不是linux系統的庫,所以在進行編譯的時候要加上-lpthread,否則編譯不過,會出現下面錯誤
thread_test.c: 在函數 ‘create’ 中:
thread_test.c:7: 警告: 在有返回值的函數中,程序流程到達函數尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):對‘pthread_create’未定義的引用
collect2: ld 返回 1

  運行,我們得到如下結果:
# ./a.out
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
....

兩個線程交替執行。
此例子介紹了創建線程的方法。
下面例子介紹向線程傳遞參數。


例程2:
    功能:向新的線程傳遞整形值
    程序名稱:pthread_int.c
/********************************************************************************************
**    Name:pthread_int.c
**    Used to study the multithread programming in Linux OS
**    Pass a parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *create(void *arg)
{
    int *num;
    num=(int *)arg;
    printf("create parameter is %d \n",*num);
    return (void *)0;
}
int main(int argc ,char *argv[])
{
    pthread_t tidp;
    int error;
   
    int test=4;
    int *attr=&test;
   
    error=pthread_create(&tidp,NULL,create,(void *)attr);

    if(error)
        {
        printf("pthread_create is created is not created ... \n");
        return -1;
        }
    sleep(1);
    printf("pthread_create is created ...\n");
    return 0;       
}


    編譯方法:

gcc -lpthread pthread_int.c -Wall


    執行結果:

create parameter is 4
pthread_create is created is  created ...


    例程總結:
    可以看出來,我們在main函數中傳遞的整行指針,傳遞到我們新建的線程函數中。
    在上面的例子可以看出來我們向新的線程傳入了另一個線程的int數據,線程之間還可以傳遞字符串或是更復雜的數據結構。
例程3:
    程序功能:向新建的線程傳遞字符串
        程序名稱:pthread_string.c
/********************************************************************************************
**    Name:pthread_string.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *create(void *arg)
{
    char *name;
    name=(char *)arg;
    printf("The parameter passed from main function is %s  \n",name);
    return (void *)0;
}

int main(int argc, char *argv[])
{
    char *a="zieckey";
    int error;
    pthread_t tidp;

    error=pthread_create(&tidp, NULL, create, (void *)a);

    if(error!=0)
    {
        printf("pthread is not created.\n");
        return -1;
    }
    sleep(1);
    printf("pthread is created... \n");
    return 0;
}   

  編譯方法:

gcc -Wall pthread_string.c -lpthread


    執行結果:
The parameter passed from main function is zieckey 
pthread is created...


    例程總結:
    可以看出來main函數中的字符串傳入了新建的線程中。

例程4:
    程序功能:向新建的線程傳遞字符串
        程序名稱:pthread_struct.c
/********************************************************************************************
**    Name:pthread_struct.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

struct menber
{
    int a;
    char *s;
};

void *create(void *arg)
{
    struct menber *temp;
    temp=(struct menber *)arg;
    printf("menber->a = %d  \n",temp->a);
    printf("menber->s = %s  \n",temp->s);
    return (void *)0;
}

int main(int argc,char *argv[])
{
    pthread_t tidp;
    int error;
    struct menber *b;
    b=(struct menber *)malloc( sizeof(struct menber) );
    b->a = 4;
    b->s = "zieckey";

    error = pthread_create(&tidp, NULL, create, (void *)b);

    if( error )
    {
        printf("phread is not created...\n");
        return -1;
    }
    sleep(1);
    printf("pthread is created...\n");
    return 0;
}

  編譯方法:

gcc -Wall pthread_struct.c -lpthread


    執行結果:
menber->a = 4 
menber->s = zieckey 
pthread is created...

    例程總結:
    可以看出來main函數中的一個結構體傳入了新建的線程中。
    線程包含了標識進程內執行環境必須的信息。他集成了進程中的所有信息都是對線程進行共享的,包括文本程序、程序的全局內存和堆內存、棧以及文件描述符。
   

例程5:
    程序目的:驗證新建立的線程可以共享進程中的數據
    程序名稱:pthread_share.c 

/********************************************************************************************
**    Name:pthread_share_data.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

static int a=4;
void *create(void *arg)
{
    printf("new pthread ... \n");
    printf("a=%d  \n",a);
    return (void *)0;
}

int main(int argc,char *argv[])
{
    pthread_t tidp;
    int error;
   
    a=5;

    error=pthread_create(&tidp, NULL, create, NULL);

    if(error!=0)
    {
        printf("new thread is not create ... \n");
        return -1;
    }
   
    sleep(1);
   
    printf("new thread is created ... \n");
    return 0;
}
   
  編譯方法:

gcc -Wall pthread_share_data.c -lpthread


    執行結果:
new pthread ...
a=5 
new thread is created ...


    例程總結:
可以看出來,我們在主線程更改了我們的全局變量a的值的時候,我們新建立的線程則打印出來了改變的值,可以看出可以訪問線程所在進程中的數據信息。
2、線程的終止

    如果進程中任何一個線程中調用exit,_Exit,或者是_exit,那么整個進程就會終止,
    與此類似,如果信號的默認的動作是終止進程,那么,把該信號發送到線程會終止進程。
    線程的正常退出的方式:
       (1) 線程只是從啟動例程中返回,返回值是線程中的退出碼
       (2) 線程可以被另一個進程進行終止
       (3) 線程自己調用pthread_exit函數
    兩個重要的函數原型:

#include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr 線程退出返回的指針*/

int pthread_join(pthread_t thread,void **rval_ptr);
   /*成功結束進程為0,否則為錯誤編碼*/


    例程6
    程序目的:線程正常退出,接受線程退出的返回碼
    程序名稱:pthread_exit.c

/********************************************************************************************
**    Name:pthread_exit.c
**    Used to study the multithread programming in Linux OS
**    A example showing a thread to exit and with a return code.
**    Author:zeickey
**    Date:2006/9/16        
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *create(void *arg)
{
    printf("new thread is created ... \n");
    return (void *)8;
}

int main(int argc,char *argv[])
{
    pthread_t tid;
    int error;
    void *temp;

    error = pthread_create(&tid, NULL, create, NULL);

    if( error )
    {
        printf("thread is not created ... \n");
        return -1;
    }
    error = pthread_join(tid, &temp);

    if( error )
    {
        printf("thread is not exit ... \n");
        return -2;
    }
    
    printf("thread is exit code %d \n", (int )temp);
    return 0;
}

  編譯方法:

gcc -Wall pthread_exit.c -lpthread


    執行結果:
new thread is created ...
thread is exit code 8

    例程總結:
可以看出來,線程退出可以返回線程的int數值。線程退出不僅僅可以返回線程的int數值,還可以返回一個復雜的數據結構。

    例程7
    程序目的:線程結束返回一個復雜的數據結構
    程序名稱:pthread_return_struct.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct menber
{
    int a;
    char *b;
}temp={8,"zieckey"};
void *create(void *arg)
{
    printf("new thread ... \n");
    return (void *)&temp;
}

int main(int argc,char *argv[])
{
    int error;
    pthread_t tid;
    struct menber *c;

    error = pthread_create(&tid, NULL, create, NULL);
   
    if( error )
    {
        printf("new thread is not created ... \n");
        return -1;
    }
    printf("main ... \n");

    error = pthread_join(tid,(void *)&c);

    if( error )
    {
        printf("new thread is not exit ... \n");
        return -2;
    }
    printf("c->a = %d  \n",c->a);
    printf("c->b = %s  \n",c->b);
    sleep(1);
    return 0;
}


  編譯方法:

gcc -Wall pthread_return_struct.c -lpthread


    執行結果:

main ...
new thread ...
c->a = 8
c->b = zieckey


例程總結:
一定要記得返回的數據結構要是在這個數據要返回的結構沒有釋放的時候應用,
如果數據結構已經發生變化,那返回的就不會是我們所需要的,而是臟數據
3、線程標識

    函數原型:
   
#include <pthread.h>
pthread_t pthread_self(void);

pid_t getpid(void);
    getpid()用來取得目前進程的進程識別碼,函數說明

    例程8
    程序目的:實現在新建立的線程中打印該線程的id和進程id
    程序名稱:pthread_id.c
  
/********************************************************************************************
**    Name:pthread_id.c
**    Used to study the multithread programming in Linux OS.
**    Showing how to get the thread's tid and the process's pid.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> /*getpid()*/

void *create(void *arg)
{
    printf("New thread .... \n");
    printf("This thread's id is %u  \n", (unsigned int)pthread_self());
    printf("The process pid is %d  \n",getpid());
    return (void *)0;
}

int main(int argc,char *argv[])
{
    pthread_t tid;
    int error;

    printf("Main thread is starting ... \n");

    error = pthread_create(&tid, NULL, create, NULL);

    if(error)
    {
        printf("thread is not created ... \n");
        return -1;
    }
    printf("The main process's pid is %d  \n",getpid());
    sleep(1);
    return 0;
}


    編譯方法:

  
gcc -Wall -lpthread pthread_id.c

    執行結果:

Main thread is starting ...
The main process's pid is 3307 
New thread ....
This thread's id is 3086347152 
The process pid is 3307 

posted on 2008-10-13 15:35 閱讀(3939) 評論(3)  編輯 收藏 引用 所屬分類: liunx編程技術

評論

# re: Linux下多線程編程詳解  回復  更多評論   

void* (start_rtn)(void) 返回值是void類型的指針函數

應該是返回值是void*類型的函數指針吧
2013-06-03 22:13 | momognu

# re: Linux下多線程編程詳解  回復  更多評論   

void * (*start_rtn)(void) 返回值是void類型的函數指針
2013-06-03 22:28 | momognu

# re: Linux下多線程編程詳解  回復  更多評論   


void * (*start_rtn)(void *);
倒下了
2013-06-04 00:29 | momognu
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日韩国产限制| 一本色道久久综合亚洲精品按摩 | 亚洲福利电影| 久久天堂av综合合色| 欧美伊久线香蕉线新在线| 午夜精品久久久久久久蜜桃app| 亚洲午夜精品一区二区| 亚洲在线成人精品| 欧美在线视频一区二区三区| 久久综合九色综合网站| 亚洲国产成人av| 日韩视频在线一区二区| 亚洲欧美日韩综合aⅴ视频| 久久精品中文字幕一区二区三区| 蜜臀久久99精品久久久久久9 | 亚洲欧美日韩一区在线| 久久国产精品色婷婷| 欧美激情一区二区三区在线视频| 欧美日韩亚洲视频一区| 国产视频在线观看一区二区三区 | 久久精品国产清自在天天线| 久久亚洲国产精品日日av夜夜| 欧美成人精品福利| 一本色道久久综合狠狠躁篇怎么玩 | 亚洲国产精品久久久久婷婷884| 99在线热播精品免费99热| 性欧美暴力猛交69hd| 欧美高清视频免费观看| 亚洲综合电影| 欧美成人午夜激情在线| 国产麻豆综合| 宅男精品视频| 欧美国产大片| 久久久999| 国产精品一区二区三区久久 | 国产一区二区三区av电影| 亚洲黄色成人| 久久久久成人精品| 一区二区三区你懂的| 亚洲欧洲av一区二区三区久久| 国产永久精品大片wwwapp| 亚洲日本中文字幕区| 欧美在线视频观看免费网站| 亚洲理论电影网| 另类av导航| 国内精品久久久久久久影视蜜臀| 一区二区三区欧美激情| 欧美国产日韩视频| 欧美在线日韩| 国产欧美一区在线| 性色av一区二区三区在线观看| 亚洲欧洲精品一区二区三区波多野1战4| 香蕉国产精品偷在线观看不卡| 欧美午夜视频一区二区| 一区二区欧美精品| 亚洲人成小说网站色在线| 男人天堂欧美日韩| 91久久精品国产91久久性色| 久久在线视频| 久久蜜桃资源一区二区老牛 | 亚洲欧洲一区二区三区| 看片网站欧美日韩| 久久久久久久一区二区三区| 国产一区日韩二区欧美三区| 久久av资源网| 久久久99久久精品女同性| 禁久久精品乱码| 欧美国产亚洲视频| 欧美精品福利视频| 亚洲网址在线| 亚洲综合三区| 黑人巨大精品欧美一区二区| 久久亚洲精品网站| 久久久久国产精品厨房| 91久久精品日日躁夜夜躁欧美| 欧美成人蜜桃| 欧美区国产区| 久久aⅴ国产紧身牛仔裤| 久久国产色av| 亚洲精品日韩一| 宅男噜噜噜66一区二区66| 国产欧美一区二区色老头| 欧美va亚洲va香蕉在线| 欧美日韩播放| 久久精品日韩一区二区三区| 久久综合99re88久久爱| 在线综合亚洲欧美在线视频| 午夜国产精品影院在线观看| 在线观看亚洲| 夜夜精品视频| 精品999成人| 99精品国产一区二区青青牛奶| 国产美女高潮久久白浆| 欧美a一区二区| 国产精品人人做人人爽| 欧美激情片在线观看| 欧美揉bbbbb揉bbbbb| 黄色成人在线网址| 中文国产成人精品久久一| 午夜精品福利在线| 亚洲日本理论电影| 亚洲欧美日韩一区在线观看| 亚洲久久在线| 久久福利资源站| 亚洲一卡二卡三卡四卡五卡| 久久久久这里只有精品| 亚洲免费网址| 欧美国产精品久久| 久久深夜福利免费观看| 欧美日韩久久久久久| 麻豆精品一区二区综合av| 国产精品大片wwwwww| 欧美黄色免费| 精品动漫3d一区二区三区免费版 | 亚洲美女免费视频| 欧美一区深夜视频| 亚洲欧美激情精品一区二区| 蜜桃久久av| 久久天天躁夜夜躁狠狠躁2022| 欧美日韩在线免费| 亚洲黄色毛片| 亚洲激情国产| 久久网站免费| 美女国产一区| 国产一区二区三区高清在线观看 | 久久久中精品2020中文| 欧美亚洲一区二区在线观看| 欧美性大战久久久久久久| 亚洲毛片网站| 99国产精品99久久久久久粉嫩| 久久免费高清| 免费一级欧美在线大片| 尤物精品在线| 久久女同精品一区二区| 美日韩免费视频| 有坂深雪在线一区| 久久这里只有精品视频首页| 麻豆成人精品| 亚洲电影欧美电影有声小说| 久久久之久亚州精品露出| 久热爱精品视频线路一| 黄色欧美成人| 蜜臀av性久久久久蜜臀aⅴ四虎| 欧美成人资源| 日韩一区二区福利| 欧美视频在线一区| 午夜激情久久久| 久久精品中文字幕一区| 一区二区三区在线免费观看| 久久一区国产| 亚洲精品一区二区三区在线观看 | 亚洲午夜小视频| 午夜精品久久久久久久99樱桃 | 欧美电影免费观看网站| 亚洲成人在线网| 亚洲作爱视频| 国产精品夜夜夜| 欧美在线你懂的| 欧美高清在线精品一区| 99在线观看免费视频精品观看| 欧美午夜一区二区三区免费大片 | 国产精品三级视频| 久久国产精彩视频| 亚洲欧洲日韩在线| 欧美一区二区三区啪啪| 在线免费观看成人网| 欧美激情亚洲自拍| 亚洲欧美在线x视频| 亚洲第一网站免费视频| 亚洲欧美中文日韩在线| 亚洲丰满少妇videoshd| 欧美午夜电影在线观看| 欧美一区二区啪啪| 亚洲破处大片| 久久九九热re6这里有精品| 亚洲美女中文字幕| 国产伦精品一区二区三区照片91| 久久免费99精品久久久久久| 一区二区精品在线观看| 欧美韩日一区二区| 午夜一区不卡| 99精品欧美一区| 国产在线视频不卡二| 欧美日韩国产探花| 久久综合网络一区二区| 亚洲欧美国产高清| 亚洲激情成人在线| 猛男gaygay欧美视频| 午夜一区二区三区不卡视频| 日韩视频精品在线| 黑人巨大精品欧美黑白配亚洲| 欧美视频日韩视频| 欧美成人一区在线| 久久免费的精品国产v∧| 午夜亚洲福利| 一本色道久久综合狠狠躁篇怎么玩 | 亚洲人成77777在线观看网| 久久综合网络一区二区| 久久精品久久综合| 久久精品亚洲乱码伦伦中文 |