Unix編程 第十一章 線程

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2)

對比兩個線程id是否相等

#include <pthread.h>
pthread_t pthread_self(void)

獲取自身的tid

3.創(chuàng)建線程

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); 成功返回0,否則返回錯誤編號

當(dāng)函數(shù)成功返回的時候绳瘟,新創(chuàng)建的線程ID會被設(shè)置成tidp指向的內(nèi)存單元慨菱。
新創(chuàng)建的線程從start_rtn函數(shù)的地址開始運(yùn)行杖小,該函數(shù)只有一個無類型的指針參數(shù)arg列林。如果需要向start_rtn傳遞的參數(shù)有一個以上终吼,需要把這些參數(shù)放到一個結(jié)構(gòu)中贞盯,然后將結(jié)構(gòu)地址作為arg參數(shù)傳入

4.線程終止
1.線程正常返回音念,返回值是線程的退出碼
2.倍同一進(jìn)程中的其他線程取消
3.線程調(diào)用pthread_exit

#include <pthread.h>
void pthread_exit(void *rval_ptr)
int pthread_join(pthread_t thread, void **rval_ptr);

如果線程調(diào)用pthread_join 將會一直阻塞,直到指定的線程調(diào)用pthread_exit,或者從啟動歷程中返回或者被取消躏敢。
如果只是從它的啟動例程返回,rval_ptr就包含返回碼闷愤。如果線程被取消,rval_ptr指定的內(nèi)存單元會被設(shè)置成PTHREAD_CANCELED件余。如果不關(guān)心返回值讥脐,可以把rval_ptr設(shè)為NULL。

5.線程取消

#include <pthread.h>
int pthread_cancel(pthread_t tid);
//成功返回 0 否則返回錯誤編號

該函數(shù)并不等待線程終止啼器,只是提出請求

6.線程退出清理

#include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);

觸發(fā)時機(jī):
當(dāng)調(diào)用pthread_exit時
響應(yīng)取消請求時
execute設(shè)置非0時
execute設(shè)置為0時旬渠,將刪除上一次 pthread_cleanup_push調(diào)用建立的程序

進(jìn)程函數(shù)與線程函數(shù)對比


image.png

7.線程同步
增量操作通常分三步
1.把內(nèi)存單元讀入寄存器
2.把寄存器中對變量做增量操作
3.把新的值寫回單元

8.互斥量(mutex)
本質(zhì)上是一把鎖,在訪問共享資源前對mutex進(jìn)行設(shè)置(加鎖)端壳,訪問完成后釋放(解鎖)互斥量告丢。
任何其他試圖再次對互斥量加鎖的都會被阻塞,直到當(dāng)前線程釋放互斥量损谦。如果釋放互斥量時有一個以上的線程阻塞岖免,那么所有該鎖上的阻塞線程都會變成可運(yùn)行狀態(tài)岳颇,第一個變?yōu)榭蛇\(yùn)行的線程就可以對互斥量加鎖。
如果允許其中的某一個線程在沒有加鎖的情況下訪問共享資源觅捆,那么互斥量就沒用了

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
                                     const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(phtread_mutex_t *mutex);
//成功返回0 否則返回錯誤編號

默認(rèn)初始化變量只需要把a(bǔ)ttr設(shè)置為NULL

#include<pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex)
//成功返回 0 否則返回錯誤編號

如果線程不希望被阻塞赦役,可以使用trylock嘗試對互斥量進(jìn)行加鎖,如果處于未鎖住狀態(tài)栅炒,就鎖住互斥量 掂摔,如果成功返回0,鎖住互斥量赢赊,否則失敗乙漓,返回EBUSY

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

struct foo{
    int     f_count;
    pthread_mutex_t f_lock;
    int     f_id;
};

struct foo*
fool_alloc(int id)
{
    struct foo *fp;

    if((fp = (struct foo*)malloc(sizeof(struct foo))) != NULL){
        fp->f_count = 1;
        fp->f_id = id;
        if(pthread_mutex_init(&fp->f_lock,NULL) != 0){
            free(fp);
            return NULL;
        }
    }

    return fp;
}

void 
foo_hold(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}

void
foo_rele(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    if(--fp->f_count == 0){
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
    }

}

9.避免死鎖
如果線程試圖對同一個互斥量加鎖兩次,那么自身就會陷入死鎖狀態(tài)释移。
程序中使用一個以上的互斥量時叭披,如果允許一個線程一直占用第一個互斥量,并且試圖在鎖住第二個互斥量時處于阻塞狀態(tài)玩讳,擁有第二個互斥量的線程也在試圖鎖住第一個互斥量涩蜘,互相都不釋放鎖并且阻塞的情況。
假設(shè) 需要對互斥量AB同時加鎖熏纯。如果所有線程總是在互斥量B加鎖之前鎖住互斥量A同诫,那么使用這兩個互斥量就不會產(chǎn)生死鎖。
如果涉及太多的鎖和數(shù)據(jù)結(jié)構(gòu)樟澜,可以采用另外的方法误窖。在這種情況下,可以先釋放占有的鎖秩贰,然后過一段時間再試霹俺。這種情況可以使用pthread_mutex_trylock接口避免死鎖,如果已經(jīng)占用某些鎖 而且pthread_mutex_trylock接口返回成功毒费,那么就可以繼續(xù)丙唧。

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

#define NHASH 29
#define HASH(id) (((unsigned long)id) % NHASH)

struct foo *fh[NHASH]; //pointer to array fh

pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER; 


struct foo{
    int     f_count;
    pthread_mutex_t f_lock;
    int     f_id;
    struct foo * f_next; //pointer to next foo

    /***more stuff.....***/
};

struct foo*
fool_alloc(int id)
{
    struct foo *fp;
    int idx;

    if((fp = (struct foo*)malloc(sizeof(struct foo))) != NULL){  //allocate memory of object foo
        fp->f_count = 1;
        fp->f_id = id;
        if(pthread_mutex_init(&fp->f_lock,NULL) != 0){
            free(fp); //if mutex init error free memory of struct foo fp;
            return NULL;    
        }
        idx = HASH(id);
        pthread_mutex_lock(&hashlock);
        fp->f_next = fh[idx];
        fh[idx] = fp;
        pthread_mutex_lock(&fp->f_lock);
        pthread_mutex_unlock(&hashlock);
        pthread_mutex_unlock(&fp->f_lock);
    }

    return fp;
}

void 
foo_hold(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}


struct foo*
foo_find(int id)
{
    struct foo *fp;

    pthread_mutex_lock(&hashlock);
    for(fp = fh[HASH(id)]; fp != NULL; fp = fp->f_next){
        if(fp->f_id == id) {
            foo_hold(fp);
            break;
        }
    }
    pthread_mutex_unlock(&hashlock);
    return fp;
}


void
foo_rele(struct foo *fp)
{
    struct foo *tfp;
    int idx;

    pthread_mutex_lock(&fp->f_lock);
    if(fp->f_count == 1){
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_lock(&hashlock);
        pthread_mutex_lock(&fp->f_lock);

        if(fp->f_count != 1){
            fp->f_count--;
            pthread_mutex_unlock(&fp->f_lock);
            pthread_mutex_unlock(&hashlock);
            return;
        } 
        idx = HASH(fp->f_id);
        tfp = fh[idx];
        if(tfp == fp){
            fh[idx] = fp->f_next;
        }else
        {
            while(tfp->f_next != fp)
                tfp = tfp->f_next;
            tfp->f_next = fp->f_next;
        }

        pthread_mutex_unlock(&hashlock);
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
    }
    else{
        fp->f_count--;
        pthread_mutex_destroy(&fp->f_lock);
    }
}

上面的功能可以看出 鎖的顆粒度的大小嚴(yán)重影響多線程程序的復(fù)雜度 顆粒度越小 復(fù)雜度越大

10.pthread_mutex_timedlock


image.png

訪問已加鎖的互斥量的時候,允許綁定一個時間觅玻,如果在這個時間內(nèi)都沒有加上鎖想际,那么就會返回 ETIMEDOUT

11.讀寫鎖 (reader-writer lock)或者叫共享互斥鎖(shared-exclusive lock)
1.讀模式下加鎖 有多線程可以占有
2.寫模式下加鎖 一次只有一個線程可以占有
3.不加鎖

當(dāng)讀寫鎖 是處于寫加鎖狀態(tài)的時候,所有試圖訪問該鎖的線程都會阻塞串塑。
當(dāng)讀寫鎖 是處于讀加鎖狀態(tài)的時候沼琉,所有以讀模式對它進(jìn)行加鎖的線程都可以得到訪問權(quán)限,但是以寫模式對此進(jìn)行加鎖的線程都會阻塞桩匪,一直到所有線程都釋放他們的讀鎖位置 (當(dāng)以寫模式對此進(jìn)行加鎖到來的時候打瘪,后續(xù)進(jìn)行的讀模式進(jìn)行加鎖都會被阻塞,為了防止出現(xiàn)等待的寫模式鎖的請求一直得不到滿足的情況)

讀寫鎖非常適用于數(shù)據(jù)結(jié)構(gòu)的讀取遠(yuǎn)大于寫的情況

初始化:

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t * restrict rwlock,
                                      const pthread_rwlockattr_t * restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

//成功返回0  否則返回錯誤編號

讀寫鎖操作:

#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
//成功返回0  否則返回錯誤編號
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

可以獲取鎖的時候返回0,否則返回EBUSY

代碼示例:
多個工作線程獲取單個主線程分配給他們的作業(yè)

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

struct job {
    struct job *j_next;
    struct job *j_prev;
    pthread_t j_id;
    /** stuff here**/
};

struct queue{
    struct job *q_head;
    struct job *q_tail;
    pthread_rwlock_t q_lock;
};


/*
*Initialize a queue
*/
int
queue_init(struct queue *qp)
{
    int err;
    qp->q_head = NULL;
    qp->q_tail = NULL;
    err = pthread_rwlock_init(&qp->q_lock,NULL);
    if(err != 0)
    {
        return(err);
    }

    /**continue init data....**/
    return 0;
};


/*
*Insert a job at the head of the queue.
*/
void 
job_insert(struct queue *qp , struct job *jb)
{
    pthread_rwlock_wrlock(&qp->q_lock); // lock with read mod 
    jb->j_next = qp->q_head;
    jb->j_prev = NULL;
    if(qp->q_head != NULL)
        qp->q_head->j_prev = jb;
    else
        qp->q_tail = jb; /* list was empty*/

    qp->q_head = jb;
    pthread_rwlock_unlock(&qp->q_lock);
}


/*
*   Append a job on the tail of the queue
*/
void 
job_append(struct queue *qp , struct job *jb)
{
    pthread_rwlock_wrlock(&qp->q_lock);
    jb->j_next = NULL;
    jb->j_prev = qp->q_tail;
    if(qp->q_tail != NULL)
        qp->q_tail->j_next = jb;
    else
        qp->q_head->j_next = jb;
    qp->q_tail = jb;

    pthread_rwlock_unlock(&qp->q_lock);
}

/*
 *Remove the given job from a queue 
 */
void 
job_remove(struct queue *qp, struct job *jb)
{
    pthread_rwlock_wrlock(&qp->q_lock);
    if(jb == qp->q_head){  //if job at the head of a queue
        qp->q_head = jb->j_next;
        if(qp->q_tail == jb)  // if only one job
            qp->q_tail = NULL;
        else
            jb->j_next->j_prev = jb->j_prev;
    }
    else if (jb == qp->q_tail){
        qp->q_tail = jb->j_prev;//if job at the head of a queue
        jb->j_prev->j_next = jb->j_next;
    } else {
        jb->j_prev->j_next = jb->j_next;
        jb->j_next->j_prev = jb->j_prev;
    }
    pthread_rwlock_unlock(&qp->q_lock);
}


/*
*Find a job by given thread ID
*/
struct job *
job_find(struct queue *qp, pthread_t id)
{
    struct job *jp;
    if(pthread_rwlock_rdlock(&qp->q_lock) != 0)
        return NULL;
    
    for(jp = qp->q_head ; jp != NULL ;jp = jp->j_next)
        if(pthread_equal(jp->j_id,id))
            break;

    pthread_rwlock_unlock(&qp->q_lock);

    return jp;
}

12.條件變量
條件變量本身是由互斥量保護(hù)的闺骚。所以改變條件狀態(tài)之前必須首先鎖住互斥量彩扔。

初始化:

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, 
                                   const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

//成功返回0 否則返回錯誤編號

使用接口:

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond,
                                    pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
                                             pthread_mutex_t *restrict mutex,
                                             const struct timespec *restrict tsptr);
//當(dāng)條件滿足時 返回0 否則 阻塞 如果錯誤返回錯誤編號

使用wait的時候 mutex必須是鎖住的,函數(shù)自動把調(diào)用線程放到等待條件的線程列表上僻爽,然后對互斥量進(jìn)行解鎖虫碉。
當(dāng)wait函數(shù)返回時,互斥量再次被鎖住胸梆。

通知條件已滿足

#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);  //至少喚醒一個等待該條件線程
int pthread_cond_broadcast(pthread_cond_t *cond); //喚醒等待該條件的所有進(jìn)程
//成功返回0  錯誤返回錯誤編號

一定要在改變條件狀態(tài)后再給線程發(fā)信號

代碼示例

#include <pthread.h>

struct msg{
    struct msg *m_next;
    /*more stuff here*/
};

struct msg *workq;

pthread_cond_t qready = PTHREAD_COND_INITIALIZER;

pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;


void 
process_msg(void)
{
    struct msg *mp;

    for(;;){
        pthread_mutex_lock(&qlock);
        while(workq == NULL)
        {
            pthread_cond_wait(&qready, &qlock); 

            mp = workq;
            workq = mp->m_next;
            pthread_mutex_unlock(&qlock);
        }
    }
}

void 
enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);
}

process_msg中 先鎖住qlock互斥量敦捧,如果工作隊列wq為空,則需要等待qready條件碰镜,此時把qlock鎖釋放掉兢卵,線程阻塞,一直到有某個線程調(diào)用了 enqueue_msg 通知qready已經(jīng)ok绪颖,線程被喚醒 然后繼續(xù)執(zhí)行下面的工作處理邏輯秽荤。

13.自旋鎖
與互斥量相似,但是不是通過休眠使進(jìn)程阻塞柠横,而是在獲取鎖之前一直處于忙等(自旋)阻塞狀態(tài)窃款。
用于:鎖被持有的時間短。

#include <pthread.h>
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
//成功返回0  否則返回錯誤編號

pshared參數(shù)表示進(jìn)程共享屬性牍氛,表面自旋鎖是如何獲取的晨继。
如果設(shè)置為:PTHREAD_PROCESS_SHARED 則該鎖可以被 可以訪問鎖底層內(nèi)存的線程 所獲取
否則設(shè)置為:PTHREAD_PROCESS_PRIVATE 只能被初始化該鎖的 進(jìn)程內(nèi)部的線程 所訪問

14.屏障
屏障允許每個線程等待,直到所有的合作線程都到達(dá)某個點(diǎn)糜俗,然后從該點(diǎn)繼續(xù)執(zhí)行踱稍。

#include <pthread.h>

int pthread_barrier_init(pthread_barrier_t *restrict barrier,
                                     const pthread_barrierattr_t *restrict attr,
                                      unsigned int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);

int pthread_barrier_wait(pthread_barrier_t * barrier); //返回0 或者PTHREAD_BARRIER_SERIAL_THREAD 否則返回錯誤編號

count : 在允許所以線程繼續(xù)允許之前曲饱,必須到達(dá)屏障的線程數(shù)目悠抹。

調(diào)用wait函數(shù)的線程在屏障計數(shù),未滿足條件的時候扩淀,會進(jìn)入休眠狀態(tài)楔敌。如果這個線程是最后一個調(diào)用pthread_barrier_wait的線程,就滿足了屏障計數(shù)驻谆,所有的線程都被喚醒卵凑。

對于任一一個線程,如果wait函數(shù)返回了PTHREAD_BARRIER_SERIAL_THREAD胜臊。說明這個線程可以作為主線程勺卢,剩下的線程返回值只會為0。
一旦達(dá)到屏障計數(shù)值象对,并且線程處于非阻塞狀態(tài)黑忱,屏障就可以被復(fù)用。
但是在destroy之后,又調(diào)用init 時會對計數(shù)器進(jìn)行初始化甫煞。否則復(fù)用的時候計數(shù)器不會改變

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菇曲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抚吠,更是在濱河造成了極大的恐慌常潮,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楷力,死亡現(xiàn)場離奇詭異喊式,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)萧朝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門垃帅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人剪勿,你說我怎么就攤上這事贸诚。” “怎么了厕吉?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵酱固,是天一觀的道長。 經(jīng)常有香客問我头朱,道長运悲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任项钮,我火速辦了婚禮班眯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烁巫。我一直安慰自己署隘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布亚隙。 她就那樣靜靜地躺著磁餐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阿弃。 梳的紋絲不亂的頭發(fā)上诊霹,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機(jī)與錄音渣淳,去河邊找鬼脾还。 笑死,一個胖子當(dāng)著我的面吹牛入愧,可吹牛的內(nèi)容都是我干的鄙漏。 我是一名探鬼主播赛蔫,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泥张!你這毒婦竟也來了呵恢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤媚创,失蹤者是張志新(化名)和其女友劉穎渗钉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钞钙,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳄橘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芒炼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘫怜。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖本刽,靈堂內(nèi)的尸體忽然破棺而出鲸湃,到底是詐尸還是另有隱情,我是刑警寧澤子寓,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布暗挑,位于F島的核電站,受9級特大地震影響斜友,放射性物質(zhì)發(fā)生泄漏炸裆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一鲜屏、第九天 我趴在偏房一處隱蔽的房頂上張望烹看。 院中可真熱鬧,春花似錦洛史、人聲如沸惯殊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽靠胜。三九已至掉瞳,卻和暖如春毕源,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背陕习。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工霎褐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人该镣。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓冻璃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子省艳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 線程 線程的概念 典型的UNIX進(jìn)程可以看成只有一個控制線程:一個進(jìn)程在同一時刻只做一件事娘纷。有了多個控制線程后,在...
    ColdWave閱讀 1,453評論 0 0
  • 線程概念 典型的UNIX進(jìn)程可以看作只有一個控制線程跋炕,任務(wù)的執(zhí)行只能串行來做赖晶。有了多個控制線程后,就可以同時做多個...
    pangqiu閱讀 377評論 0 2
  • 5辐烂、線程終止 當(dāng)進(jìn)程的任何一個線程調(diào)用 exit , _exit 或者 _Exit 的時候遏插,整個進(jìn)程都會被終止。類...
    QuietHeart閱讀 118評論 0 1
  • 原型: #include int pthread_eaual(pthread_t tid1,p...
    不合格碼農(nóng)閱讀 125評論 0 0
  • 10.1 引言 在前面的章節(jié)中討論了進(jìn)程纠修,學(xué)習(xí)了UNIX進(jìn)程的環(huán)境胳嘲、進(jìn)程間的 關(guān)系以及控制進(jìn)程的不同方式】鄄荩可以看到...
    MachinePlay閱讀 481評論 0 0