-
系統(tǒng)編程第四天
今天講的都是線程相關(guān)內(nèi)容,而且這些內(nèi)容不能放在進(jìn)程中使用迅矛。個人感覺最大難點(diǎn)還是代碼的實(shí)際應(yīng)用,其他的通過老師的代碼還是可以看明白,最后一個線程鎖老師直接放在鏈表里面講了,而且還聲明這塊內(nèi)容以后肯定要用到的,要會用,不知道是不是例子涉及到鏈表了,感覺線程鎖還是沒搞懂荡碾。
最近有同學(xué)給老師提意見了,現(xiàn)在上課也能跟著老師敲代碼了,最起碼感覺效果比之前好多了,不用一直都是一臉懵逼的狀態(tài)了皂岔。
今天老師留的作業(yè)也涉及到前面的內(nèi)容,但是看了一下題目要求感覺還是那么難。
線程(thread)
- 隸屬于進(jìn)程(不可以獨(dú)立存在)
一個進(jìn)程中可以包含多個線程
如果一個進(jìn)程創(chuàng)建了n個線程,則這個進(jìn)程中包含了n+1(主線程)個線程
a. 僅有主線程的單進(jìn)程
b. 多進(jìn)程(每個進(jìn)程也僅有一個主線程)
c. 包含多個線程的單進(jìn)程
d. 包含多線程的多個進(jìn)程 - 線程僅有自己獨(dú)立的棧區(qū)(數(shù)據(jù)區(qū)苍苞、代碼區(qū)、堆區(qū)整個進(jìn)程中的所有線程共享)
- 所有線程相關(guān)函數(shù)都以pthread_XXXX開頭
所有調(diào)用線程函數(shù)的程序編譯時需加-lpthread - pthread_create
int pthread_create(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
```
5. pthread_join
```int pthread_join(pthread_t thread, void **retval);```
該函數(shù)用于對可聯(lián)結(jié)線程做善后處理狼纬,主要過程如下:
1) 等待指定線程終止
2) 獲取指定線程終止后返回的信息
3) 釋放已終止線程占用的資源
6. pthread_exit:讓調(diào)用線程從調(diào)用該函數(shù)處中途退出(不推薦使用羹呵,了解)
void pthread_cleanup_push(void (*rtn) (void *), void * arg);
void pthread_cleanup_pop(int execute);
void pthread_exit(void *retval);
```
- pthread_cancel:向指定線程發(fā)送一個取消請求(不常用,了解)
int pthread_cancel(pthread_t thread);
```
8. 線程按是否響應(yīng)取消請求分為兩種:(不常用疗琉,了解)
1) 響應(yīng)取消請求的線程(默認(rèn))
2) 不響應(yīng)取消請求的線程
int pthread_setcancelstate(int state, int *oldstate);
state取值:
PTHREAD_CANCEL_ENABLE
PTHREAD_CANCEL_DISABLE
該函數(shù)只能讓一個線程自己決定是否響應(yīng)取消請求
```
- 線程按是否可聯(lián)結(jié)分為兩種:
- 可聯(lián)結(jié)線程(默認(rèn))
- 分離的線程
創(chuàng)建線程時讓線程為分離的函數(shù):
int pthread_attr_init(pthread_attr_t * pAttr);
int pthread_attr_destroy(pthread_attr_t * pAttr);
int pthread_attr_getdetachstate(const pthread_attr_t *pAttr, int*detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *pAttr, int detachstate);
detachstate的取值:
PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
/*將已創(chuàng)建成功的線程置為分離的冈欢,過程不可逆(不推薦使用,了解)*/
int pthread_detach(pthread_t thread);
```
10. 共享資源:并行執(zhí)行的任務(wù)都可以使用資源
并行執(zhí)行的任務(wù)同時使用共享資源盈简,會出現(xiàn)沖突或數(shù)據(jù)混亂的現(xiàn)象稱為:競態(tài)”
為了解決“競態(tài)”現(xiàn)象凑耻,需要使用一種機(jī)制解決沖突,這樣的機(jī)制被稱為:同步機(jī)制
同步機(jī)制兩大核心操作:
1)P(-)操作:如果能夠獲得想要的資源立即返回柠贤,如果不能夠獲得想要的資源則排隊等待
2)V(+)操作:使用完共享資源的任務(wù)要立即調(diào)用該操作香浩,一方面將資源置空閑,另一方面通知等待使用資源的其它任務(wù)
什么是信號量:一種典型的同步機(jī)制臼勉。它不但提供了監(jiān)控可用共享資源數(shù)量的計數(shù)牌邻吭,還提供一套供沒法獲得共享資源的任務(wù)排隊用的機(jī)制
```
代碼模板:
a. 多個任務(wù)如何避免同時使用共享資源:
P操作;
...........//臨界區(qū):即使用共享資源的一段代碼
V操作
b. A任務(wù)完成一件事后通知B任務(wù)可以開始做另一件事了
A任務(wù)操作完共享資源后調(diào)V操作,B任務(wù)則在使用共享資源前調(diào)P操作
```
11. 針對多線程宴霸,Linux系統(tǒng)提供了如下幾種機(jī)制:
a. 線程信號量:多個共享資源的控制問題
頭文件:#include <semaphore.h>
類型:sem_t
初始化:int sem_init(sem_t *sem, int pshared, unsigned int value);
清理:int sem_destroy(sem_t *sem);
P操作: int sem_wait(sem_t *sem);
V操作: int sem_post(sem_t *sem);
b. 線程互斥鎖:單個共享資源的控制問題
頭文件:#include <pthread.h>
類型:pthread_mutex_t
PTHREAD_MUTEX_INITIALIZER 初始化
初始化:int pthread_mutex_init(pthread_mutex_t * mutex, NULL);
清理:int pthread_mutex_destroy(pthread_mutex_t * mutex);
阻塞P操作: int pthread_mutex_lock(pthread_mutex_t * mutex);
V操作: int pthread_mutex_unlock(pthread_mutex_t * mutex);
c. 線程讀寫鎖:讀者-寫者
頭文件:#include <pthread.h>
類型:pthread_rwlock_t
初始化:int pthread_rwlock_init(pthread_rwlock_t * rwlock, NULL);
清理:int pthread_rwlock_destroy(pthread_ rwlock _t * rwlock);
阻塞讀鎖P操作: int pthread_rwlock_rdlock(pthread_ rwlock _t * rwlock);
阻塞寫鎖P操作: int pthread_rwlock_wrlock(pthread_ rwlock _t * rwlock);
V操作: int pthread_rwlock_unlock(pthread_ rwlock _t * rwlock);
d. 線程條件變量:解決同步問題(現(xiàn)階段不要求掌握)
```
- 作業(yè):
主線程負(fù)責(zé)修改包含有10個整型數(shù)組元素的值(建議用隨機(jī)數(shù)給元素賦值)(可以每隔幾秒修改一次))
創(chuàng)建一個新的線程負(fù)責(zé)囱晴,主線程一旦修改好數(shù)組內(nèi)容膏蚓,就對該數(shù)組排序后輸出