《UNIX網路程式設計 卷2》讀書筆記(四)

2021-09-22 13:09:41 字數 3490 閱讀 9652

/* include globals */

#include    "unpipc.h"

#define    maxnitems         1000000

#define    maxnthreads            100

/* globals shared by threads */

int        nitems;                /* read-only by producer and consumer */

int        buff[maxnitems];

struct put = ;

struct nready = ;

/* end globals */

void    *produce(void *), *consume(void *);

/* include main */

intmain(int argc, char **ar**)

pthread_create(&tid_consume, null, consume, null);

/* wait for all producers and the consumer */

for (i = 0; i < nthreads; i++)

pthread_join(tid_consume, null);

exit(0); }

/* end main */

/* include prodcons */

void *

produce(void *arg)

buff[put.nput] = put.nval;

put.nput++;

put.nval++;

pthread_mutex_unlock(&put.mutex);

pthread_mutex_lock(&nready.mutex);

if (nready.nready == 0)

pthread_cond_signal(&nready.cond);//發出訊號

nready.nready++;//置為1 

pthread_mutex_unlock(&nready.mutex);

*((int *) arg) += 1; }

}void *

consume(void *arg)

return(null); }

/* end prodcons */

這裡在生產者的**中,當它獲取到互斥鎖時,若發出訊號喚醒消費者,則此時可能系統立即排程喚醒消費者,但互斥鎖任然在生產者之手,則消費者獲取互斥鎖必然失敗,為了避免此種低效的情況出現,我們可以直到生產者釋放互斥鎖後才給與之關聯的條件變數傳送訊號,這在posix裡是可以這麼做的,但posix又接著說:若要可預見的排程行為,則呼叫pthead_cond_signal的執行緒必須鎖住該互斥鎖。

當在程序間共享互斥鎖時,持有該互斥鎖的程序可能在持有期間終止,但無法讓系統在終止時自動釋放掉所持有的鎖。乙個執行緒也可以在持有互斥鎖期間終止,可能是自己呼叫pthread_exit或被另乙個執行緒取消,若是前者,則它應該知道自己還有乙個互斥鎖,若是後者,則該執行緒可以先安裝乙個將在被取消時呼叫的清理處理程式。但最致命的情況是由於此執行緒的終止導致整個程序的終止。即使乙個程序終止時系統自動釋放其持有的鎖,但也會導致臨界區內資料處於不一致狀態,

讀寫鎖的規則:

1,只要沒有執行緒持有某個給定的讀寫鎖用於寫,則任意數目的執行緒可以持有

該讀寫鎖用於讀

2,僅當沒有執行緒持有某個給定的讀寫鎖用於讀或用於寫時,才能分配該讀寫鎖用於寫

這種鎖在那些讀資料比寫資料頻繁的應用中使用比較有用,允許多個讀者提供了更高的併發度,同時在寫者修改資料時保護資料,避免任何其他讀者或寫者的干擾。

這種對某個給定資源的共享訪問也叫共享—獨佔上鎖,獲取乙個讀寫鎖用於讀稱為共享鎖,獲取乙個讀寫鎖用於寫稱為獨佔鎖。在作業系統中就介紹過這種,經典的問題就是讀者—寫者問題,有多種型別:多讀者,單寫者或多讀者,多寫者。,此外還有要考慮的就是讀者和寫者誰優先,也就產生了1類和2類讀寫問題。

讀寫鎖型別為pthread_rwlock_t。pthread_rwlock_rdlock獲取乙個讀出鎖,若對應的讀寫鎖已經被某個寫者持有,則阻塞呼叫執行緒,pthread_rwlock_wrlock獲取乙個寫出鎖,若對應的讀寫鎖已經被另乙個寫者持有或被乙個或多個讀者持有,則阻塞呼叫執行緒,pthread_rwlock_unlock釋放乙個讀出鎖或寫入鎖。

使用互斥鎖和條件變數實現讀寫鎖(寫者優先)

typedef struct pthread_rwlock_t;

int pthread_rwlock_init(pthread_rwlock_t *rw, pthread_rwlockattr_t *attr)

int pthread_rwlock_destroy(pthread_rwlock_t *rw)

int pthread_rwlock_rdlock(pthread_rwlock_t *rw)

if (result == 0)

rw->rw_refcount++;        /* another reader has a read lock */

pthread_mutex_unlock(&rw->rw_mutex);

return (result); }

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw)

int pthread_rwlock_wrlock(pthread_rwlock_t *rw)

if (result == 0)

rw->rw_refcount = -1;

pthread_mutex_unlock(&rw->rw_mutex);

return(result); }

int pthread_rwlock_trywrlock(pthread_rwlock_t *rw)

int pthread_rwlock_unlock(pthread_rwlock_t *rw)

else if (rw->rw_nwaitreaders > 0)

result = pthread_cond_broadcast(&rw->rw_condreaders);

pthread_mutex_unlock(&rw->rw_mutex);

return(result); }

int pthread_rwlock_unlock(pthread_rwlock_t *rw)

else if (rw->rw_nwaitreaders > 0)

result = pthread_cond_broadcast(&rw->rw_condreaders);//通知所有等待的讀者

pthread_mutex_unlock(&rw->rw_mutex);

return(result); }

這裡的讀出鎖和寫入鎖函式都有乙個問題,若呼叫執行緒阻塞在pthread_cond_wati呼叫上,並且隨後此執行緒被取消了,則它會在還持有互斥鎖的情況下終止,於是rw_nwaitreaders計數器的值會出錯

《UNIX網路程式設計 卷2》讀書筆記(二)

如何知道程序在乙個空訊息佇列中放入乙個訊息?如果阻塞在msgrcv呼叫中,則除了等待無法做其他事情,如果給msgrcv指定非阻塞標誌 ipc nowait 儘管不阻塞了,但必須持續呼叫該函式來確定何時有訊息到達,也就是採用輪詢方式 polling posix訊息佇列允許非同步事件通知來通知何時有訊息...

Unix網路程式設計讀書筆記(四)

unix下共有5種i o模型 阻塞式i o 非阻塞式i o i o復用 select和poll 訊號驅動式i o sigio 非同步i o posix的aio 系列函式 同步i o與非同步i o 同步i o操作導致請求程序阻塞,直到i o操作完成。前4種模型都是同步i o模型,因為其中真正的i o操...

UNIX網路程式設計卷2程序間通訊讀書筆記彙總

unix 網路程式設計卷 2程序間通訊讀書筆記 一 概述 網路程式設計卷 2程序間通訊讀書筆記 二 管道 1 網路程式設計卷 2程序間通訊讀書筆記 二 管道 2 網路程式設計卷 2程序間通訊讀書筆記 三 有名管道 1 網路程式設計卷 2程序間通訊讀書筆記 三 有名管道 2 網路程式設計卷 2程序間通...