日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Linux?多線程編程(?POSIX?)(?一?)?1.基礎(chǔ)線程創(chuàng)建:

 春華_秋實(shí) 2012-05-02

Linux 多線程編程( POSIX )( 一 ) ---->  代碼區(qū)

(2012-01-30 17:07:29)
標(biāo)簽:

雜談

分類: Linux進(jìn)程與線程
1.基礎(chǔ)線程創(chuàng)建:

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

void * print_id( void * arg )        //!> 這是線程的入口函數(shù)                               
{
    printf("The Current process is: %d \n", getpid());                                //!> 當(dāng)前進(jìn)程ID   
    printf( "The Current thread id : %d \n", (unsigned)pthread_self() );    //!> 注意此處輸出的子線程的ID
}

int main( )
{
    pthread_t        t;
    int                 t_id;
   
    t_id = pthread_create( &t, NULL, print_id, NULL );        //!> 簡(jiǎn)單的創(chuàng)建線程
   
    if( t_id != 0 )                        //!> 注意創(chuàng)建成功返回0                               
    {
        printf("\nCreate thread error...\n");
        exit( EXIT_FAILURE );
   
    sleep( 1 );
    printf("\nThe Current process is: %d \n", getpid());                         //!> 當(dāng)前進(jìn)程ID       
    printf( "The Main thread id : %d \n", (unsigned)pthread_self() );    //!> 注意輸出的MAIN線程的ID
    return 0;
}



2.測(cè)試線程的創(chuàng)建和退出

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

void * entrance_1( void * arg )                //!> 第一個(gè)創(chuàng)建的線程的入口函數(shù)
{
    printf( " thread 1 id == %d , run now ... \n", ( unsigned )pthread_self() );
    sleep( 3 );
    return ( ( void * ) 1 );
}

void * entrance_2( void * arg )                //!> 第二個(gè)創(chuàng)建的線程的入口函數(shù)
{
    printf( " thread 2 id == %d , run now ... \n", ( unsigned )pthread_self() );
    sleep( 3 );
    return ( ( void * ) 2 );
}

int main( )
{
    pthread_t        t1 = -1;    //!> 最好是初始化:因?yàn)橄旅娴膒thread_join是需要判斷是否成功在輸出的
    pthread_t        t2 = -1;
    int              tid1;
    int              tid2;
    void           ret;
   
    tid1 = pthread_create( &t1, NULL, entrance_1, NULL );    //!> 簡(jiǎn)單的創(chuàng)建線程
    tid2 = pthread_create( &t2, NULL, entrance_2, NULL );
   
    if( tid1 != 0 || tid2 != 0 )    //!> 創(chuàng)建線程失敗                   
    {
        printf( "Create thread error...\n" );
        exit( EXIT_FAILURE );
    }
   
    if( t1 != -1 )                //!> 也就是線程還沒(méi)有結(jié)束
    {
        if ( pthread_join( t1, &ret ) == 0 )    //!> join success
        {
            printf( " thread 1 get the return of pthread_join == %d \n", 2 );/ )
 {
     pthread_mutex_init( &mutex, NULL );        //!> 初始化為默認(rèn)的互斥鎖
    
     printf("主函數(shù):創(chuàng)建2個(gè)子線程...\n");
    
     create_two_thread();        //!> 創(chuàng)建2個(gè)線程
    
     printf("主函數(shù):等待線程完成任務(wù)...\n");
    
     wait_two_thread();        //!> 等待線程完成任務(wù)
                                 //!> 線程任務(wù)完成才可以執(zhí)行下面代碼
     printf("線程任務(wù)完成...\n");
    
     printf("Num == %d \n\n", num);
    
     return 0;
 }
 
4.雙線程處理:冒泡排序算法

//        雙線程處理冒泡排序(多線程也一樣)
//        實(shí)現(xiàn)從“小”--->“大”排序

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

int g_arr[] = { 10, 23, 12, 34, 5, 29, 90, 9, 78, 44 };        //!> 全局的要排序的數(shù)組
pthread_t                thread[2];               //!> 兩個(gè)線程
pthread_mutex_t        mutex;                //!> 互斥鎖

int                         g_i = 0;                     //!> 全局的剩余排列次數(shù)

//!> 打印數(shù)組
void print_array()
{
    int i;
    for( i = 0; i < 10; i++ )
    {
        printf( " %d ", g_arr[i] );
    }
    printf("\n");
}

//!> 交換元素
void swap_elem( int * a, int * b )
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

//!> 線程1入口函數(shù)
void * entrance_1( void * arg )
{
    int j;
    for( g_i = 0; g_i < 10; g_i++ )    //!> 外層循環(huán)
    {
        pthread_mutex_lock( &mutex );        //!> 加鎖
       
        printf( "線程1后臺(tái)執(zhí)行排序...\n" );
       
        for( j = 0; j < ( 10 - g_i - 1 ); j++ )    //!> 內(nèi)層循環(huán)
        {
            if( g_arr[j] > g_arr[j+1] )
            {
                swap_elem( &g_arr[j], &g_arr[j+1] );
            }
        }
       
        pthread_mutex_unlock( &mutex );    //!> 解鎖
       
        sleep( 1 );
    }
}

//!> 線程2入口函數(shù)
void * entrance_2( void * arg )
{
    int j;
    for( g_i = 0; g_i < 10; g_i++ )    //!> 外層循環(huán)
    {
        pthread_mutex_lock( &mutex );        //!> 加鎖
       
        printf( "線程2后臺(tái)執(zhí)行排序...\n" );
           
        for( j = 0; j < ( 10 - g_i - 1 ); j++ )    //!> 內(nèi)層循環(huán)
        {
            if( g_arr[j] > g_arr[j+1] )
            {
                swap_elem( &g_arr[j], &g_arr[j+1] );
            }
        }
   
        pthread_mutex_unlock( &mutex );    //!> 解鎖

        sleep( 2 );   
    }
}

//!> 創(chuàng)建2個(gè)線程
void create_two_thread()
{
    memset( &thread, 0, sizeof( thread ) );            //!> 初始化為0(作為下面的判斷進(jìn)程是否創(chuàng)建OK依據(jù))
   
    if( ( pthread_create( &thread[0], NULL, entrance_1, NULL ) ) == 0 )
    {
        printf("線程1創(chuàng)建OK ...\n");
    }
    else
    {
        printf("線程1創(chuàng)建Error ...\n");
        exit( EXIT_FAILURE );
    }
   
    if( ( pthread_create( &thread[1], NULL, entrance_2, NULL ) ) == 0 )
    {
        printf("線程2創(chuàng)建OK ...\n");
    }
    else
    {
        printf("線程2創(chuàng)建Error ...\n");
        exit( EXIT_FAILURE );
    }
   
}

//!> 線程執(zhí)行與等待
void do_and_wait()
{
    if( thread[0] != 0 )//!> 由于在create_two_thread中初始化=0,if床架ok,那么不可能還是0
    {
        pthread_join( thread[0], NULL );    //!> 等待線程1結(jié)束,不結(jié)束不執(zhí)行下面代碼
        printf("線程1執(zhí)行結(jié)束退出...\n");
    }
    else
    {
        printf("線程1創(chuàng)建Error...\n");
        exit( EXIT_FAILURE );
    }
   
    if( thread[1] != 0 )
    {
        pthread_join( thread[1], NULL );    //!> 等待線程1結(jié)束,不結(jié)束不執(zhí)行下面代碼
        printf("線程2執(zhí)行結(jié)束退出...\n");
    }
    else
    {
        printf("線程2創(chuàng)建Error...\n");
        exit( EXIT_FAILURE );
    }
   
}

int main( )
{
    printf("主函數(shù):下面創(chuàng)建2個(gè)線程共同處理冒泡排序...\n");
   
    pthread_mutex_init( &mutex, NULL );
   
    print_array();                //!> 打印排序前的結(jié)果
   
    create_two_thread();        //!> 創(chuàng)建線程
    do_and_wait();            //!> 執(zhí)行線程and等待
   
    printf( "排序完成:\n" );

    print_array();                //!> 打印排序后的結(jié)果
       
    return 0;
}

5.線程清理處理程序

//        線程清理處理程序TEST

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

void clean(void *arg)
{
    printf("清理: %s \n", (char *)arg);
}

void * entrance( void * arg )
{
    printf("線程開(kāi)始...\n");
   
    pthread_cleanup_push( clean, "線程處理程序1" );
    pthread_cleanup_push( clean, "線程處理程序2" );
   
    printf("pthread clean 完成...\n");
   
    sleep(3);
   
    pthread_exit((void *)0);        //!> 我們知道:清理函數(shù)只有在異常退出時(shí)候才會(huì)做一些清理工作
                                                //!> 所以此處的退出是異常退出來(lái)測(cè)試的!
   
    pthread_cleanup_pop(0);    
    pthread_cleanup_pop(0);    
   
   
   
}

int main( )
{
    pthread_t     tid;
    void        ret = NULL;
   
    if( ( pthread_create( &tid, NULL, entrance, (void *)1 ) ) != 0 )
    {
        printf("創(chuàng)建線程失敗...\n");
        exit( EXIT_FAILURE );
    }
   
    pthread_join( tid, &ret );       
   
    if( ret )                            //!> 注意此處相當(dāng)于是拋出異常
                                  //!> 避免子線程的異常退出造成的空指針情況
        printf( "結(jié)束:code == %d\n", *( ( int * ) ret) );
    }
   
    return 0;
}

/////////////////////////////////////////////////////////////
//    DEMO——2

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

void clean( void * arg )
{
    printf("清理函數(shù)執(zhí)行...\n");
}

void * entrance( void * arg )
{
    int old_type, old_state;
    int i = 0;
   
    pthread_cleanup_push( clean, NULL );    //!> 設(shè)置清理函數(shù)
    printf("下面設(shè)置對(duì)本線程的“取消”無(wú)效\n");
    pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &old_state );
                                                //!> 設(shè)置對(duì)本線程的“取消”無(wú)效
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&old_type);    //>>>>>>>>>>> 目標(biāo)句1
   
    while( 1 )
    {
        ++i;
        printf("子線程runing...\n");
        sleep( 2 );
        if( 5 == i )
        {
            printf("下面取消設(shè)置對(duì)本線程的“取消”無(wú)效\n");
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
        }
    }
   
    pthread_cleanup_pop( 0 );
}

int main( int argc, char ** argv )
{
    pthread_t    tid;
    int               res;
    void *          ret;
   
    pthread_create( &tid, NULL, entrance, NULL );
    sleep( 2 );
    printf("請(qǐng)求子線程退出...\n");
    pthread_cancel( tid );            //!> 請(qǐng)求子線程退出
   
    res = pthread_join( tid, &ret );    //!> 等待子線程退出
   
    if( ret != PTHREAD_CANCELED )    //!> 非安全退出
    {
        printf("pthread_join 失敗...\n");
        exit( EXIT_FAILURE );
    }
    else
    {
        printf("Success..");
    }
       
    exit( EXIT_SUCCESS );   
}


    分析:
        沒(méi)有加上“目標(biāo)句”的結(jié)果是:
                                        下面設(shè)置對(duì)本線程的“取消”無(wú)效
                                        子線程runing...
                                        請(qǐng)求子線程退出...
                                        子線程runing...
                                        子線程runing...
                                        子線程runing...
                                        子線程runing...
                                        下面取消設(shè)置對(duì)本線程的“取消”無(wú)效
                                        子線程runing...                        //!> 比下面多的
                                        清理函數(shù)執(zhí)行...
                                        Success..                                //!> 與下面不一樣的
                                       
      加上后:
                                        下面設(shè)置對(duì)本線程的“取消”無(wú)效
                                        子線程runing...
                                        請(qǐng)求子線程退出...
                                        子線程runing...
                                        子線程runing...
                                        子線程runing...
                                        子線程runing...
                                        下面取消設(shè)置對(duì)本線程的“取消”無(wú)效
                                        清理函數(shù)執(zhí)行...
                                        pthread_join 失敗...                    //!> 與上面不一樣的
                                       
       這句的作用是將取消類型設(shè)置為PTHREAD_CANCEL_ASYNCHRONOUS,即取消請(qǐng)求會(huì)被立即響應(yīng)                                   
       那么就不會(huì)再次進(jìn)入等待下一個(gè)“取消點(diǎn)”再進(jìn)行取消?。?!
   
       注意:if在while中沒(méi)有sleep,那么程序會(huì)無(wú)限r(nóng)un,我們知道sleep是相當(dāng)于是釋放一下線程,那么此時(shí)的主線程中的cancel信號(hào)又被接收到,那么if本函數(shù)可以響應(yīng)了,那么就cancle了,if將sleep去掉,那么死循環(huán)!再次解釋:所謂pthread_cancel僅僅是請(qǐng)求某個(gè)線程退出,那么究竟是不是退出還要看state和type的設(shè)置!                   



6. pthread_once 工作原理code


//        pthread_once 函數(shù)使用

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

pthread_once_t        once = PTHREAD_ONCE_INIT;    //!> once宏賦值

//!> 初始化執(zhí)行函數(shù)
void once_init( void )
{
    printf("初始化成功! 我的ID == %d\n", (unsigned)pthread_self());
}

//!> 線程入口函數(shù)
void * entrance( void * arg )
  
    printf("子線程:ID == %d \n", (unsigned)pthread_self());
    //!> once = PTHREAD_ONCE_INIT;        //!> 測(cè)試使用(下面的要求)
    pthread_once( &once, once_init );        //!> 此處也有初始化
}

//!> main函數(shù)
int main( int argc, char * argv[] )
{
    pthread_t        pid;
   
    pthread_create( &pid, NULL, entrance, NULL );

    printf("主函數(shù)ID == %d \n", (unsigned)pthread_self());
   
//!>    pthread_join( pid, NULL );            //!> 分析點(diǎn)
   
    pthread_once( &once, once_init );    //!> 調(diào)用一次初始化函數(shù)
   
    pthread_join( pid, NULL );
   
    return 0;
}

        if pthread_join是在主函數(shù)初始化后面,那么就是主函數(shù)初始化的
        結(jié)果是: 主函數(shù)ID == 441960192
                       初始化成功! 我的ID == 441960192
                      子線程:ID == 433944320
        顯而易見(jiàn)是主函數(shù)初始化的!
       
        if pthread_join是在之前,那么就是要等待子函數(shù)執(zhí)行ok后才執(zhí)行自己的下面代碼
        但是此時(shí)已經(jīng)初始化ok了,所以不在初始化!
        結(jié)果是:主函數(shù)ID == 210818816
                      子線程:ID == 202802944
                      初始化成功! 我的ID == 202802944
        顯然是子函數(shù)執(zhí)行的初始化!

        本質(zhì):   其實(shí)就是操作once變量而已,與互斥變量的本質(zhì)是一樣的!??!
                      我們可以這樣測(cè)試在entrance中加入once = PTHREAD_ONCE_INIT;
        結(jié)果是:主函數(shù)ID == 1590228736
                      初始化成功! 我的ID == 1590228736
                      子線程:ID == 1582212864
                      初始化成功! 我的ID == 1582212864
       
        感興趣的可以使用pthread_mutex_t 的互斥變量處理,效果一樣!
        還有最最簡(jiǎn)單的就是bool值處理!此處不建議!

7.pthread_key_create線程鍵 與線程存儲(chǔ)

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

pthread_once_t        once = PTHREAD_ONCE_INIT;
pthread_key_t        key;            //!> 鍵值
   
int                         g_val = 10;    //!> 傳說(shuō)中的獨(dú)享值,呵呵

void once_init_key()
  
    if( pthread_key_create( &key, NULL ) == 0 )    //!> 創(chuàng)建線程鍵值
                                                      //!>
        printf("創(chuàng)建線程鍵OK ...\n");
    }
}

void * entrance( void * arg )
{
    int * val;
    printf("子線程:ID == %d \n", (unsigned)pthread_self());
   
    pthread_setspecific( key, &g_val );               //!> 將 g_val 作為一個(gè)每個(gè)進(jìn)程的獨(dú)享值
   
    val = ( int * )pthread_getspecific( key );        //!> 取出那個(gè)值
                                                        //!> 此后對(duì)于這些量都有自己的處理方式,
                                                        //!> 名稱相同但是內(nèi)容不同!?。?nbsp;  
                                                        //!> 對(duì)于文件的處理是最好的?。?!
    printf("ID == %d, Value == %d\n",  (unsigned)pthread_self(), *val);
}


int main( )
{
    pthread_t        tid, tid2;
    void         ret1;
    void        ret2;
   
    if( pthread_create( &tid, NULL, entrance, NULL ) != 0 )            //!> 線程1
    {
        printf("創(chuàng)建線程1失敗...\n");
        exit( EXIT_FAILURE );
    }
   
    if( pthread_create( &tid2, NULL, entrance, NULL ) != 0 )            //!> 線程2
    {
        printf("創(chuàng)建線程2失敗...\n");
        exit( EXIT_FAILURE );
    }
           
    printf("主函數(shù):ID == %d \n", (unsigned)pthread_self());
       
    //!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   
   
    pthread_once( &once, once_init_key );    //!> 創(chuàng)建一個(gè)鍵值
   
    //!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   
    printf("下面等待子線程執(zhí)行ok... \n");
   
    pthread_join( tid, &ret1 );                    //!> 等待線程( 必不可少 )
    pthread_join( tid2, &ret2 );
   
    return 0;
}

結(jié)果:
    主函數(shù):ID == 1588877056
    創(chuàng)建線程鍵OK ...
    子線程:ID == 1580861184
    ID == 1580861184, Value == 10
    下面等待子線程執(zhí)行ok...
    子線程:ID == 1572468480
    ID == 1572468480, Value == 10

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多