国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

企業(yè)網(wǎng)站建設(shè)費用定金怎么做賬關(guān)鍵詞查網(wǎng)址

企業(yè)網(wǎng)站建設(shè)費用定金怎么做賬,關(guān)鍵詞查網(wǎng)址,歐力虎網(wǎng)站建設(shè),國內(nèi)網(wǎng)絡(luò)公司排名多線程&#xff08;三&#xff09;條件競爭并發(fā)程序引起的共享內(nèi)存的問題死鎖互斥鎖機制生產(chǎn)者消費者模型信號量機制解決&#xff1a;條件競爭 #include<stdio.h> #include<stdlib.h> #include<pthread.h> void* Print(char* str){printf("%s ",s…

多線程(三)

  • 條件競爭
    • 并發(fā)程序引起的共享內(nèi)存的問題
      • 死鎖
    • 互斥鎖機制
      • 生產(chǎn)者消費者模型
    • 信號量機制
  • 解決:

條件競爭

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void* Print(char* str){printf("%s ",str);
}int main(){pthread_t thread1,thread2;pthread_create(&thread1,NULL,(void*)&Print,"Hello");pthread_create(&thread2,NULL,(void*)&Print,"World");return 0;
}

編譯運行后,發(fā)現(xiàn)沒有預(yù)期輸出。

原因:主線程的退出會導(dǎo)致創(chuàng)建的線程退出

使用pthread_create函數(shù)創(chuàng)建兩個線程,兩個線程創(chuàng)建后,并不影響主線程的執(zhí)行,所以這里就存在三個線程的競爭關(guān)系。主線程執(zhí)行return 0;先于另外兩個線程的打印函數(shù)。所以看不見另外兩個線程的輸出。為了使return 0;語句在另外兩個進程后執(zhí)行,可以采用sleep()函數(shù)進行延遲,就可以得到輸出了,這就是條件競爭。

在遇到條件競爭的問題中,采用sleep()函數(shù)進行延遲似乎也能解決問題。實則不然,弊端很明顯:

  1. 不能判斷延遲的時間長度。
  2. 使程序執(zhí)行卡頓。

最適當(dāng)?shù)慕鉀Q方法是采用鎖機制。

并發(fā)程序引起的共享內(nèi)存的問題

有兩個進程,兩個進程共享全局變量s。兩個進程都執(zhí)行一個計數(shù)功能的函數(shù),直觀地看過去,th1運行時s++要執(zhí)行10000次,th2運行時s++也要執(zhí)行10000次,似乎計算得到的最后s應(yīng)該是20000。但實際上是這樣的嗎?

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int s = 0;
void *func(void*args){int i;for(i = 0; i < 10000; i++){s++;}return NULL;
}
int main(){pthread_t th1;pthread_t th2;pthread_create(&th1, NULL, func, NULL);pthread_create(&th2, NULL, func, NULL);pthread_join(th1, NULL);pthread_join(th2, NULL);printf("%s = %d\n", s);return 0;
}

編譯運行后,發(fā)現(xiàn)輸出并不是20000,而是12657。

運行了3次這個程序,每次的結(jié)果都不同。 用這個演示來表示一下,多線程之間是資源共享的。

s++ 是有三個步的,讀取s,s+1,寫入s。

在程序運行的某個時刻,th1攜帶myfunc執(zhí)行s++,讀取s,此時s=100,進行s+1, 與此同時th2也開始讀取s,此時的s還是等于100, 這時th1,執(zhí)行寫入s=101,th2執(zhí)行s++,寫入s ,s=101. th2中的s 就會覆蓋掉 th1中的s 。這樣造成了結(jié)果的誤差。

原因:當(dāng)我們執(zhí)行s++,底層發(fā)生的事件其實是:內(nèi)存中讀取s→將s+1→將s寫入到內(nèi)存。這不是一個原子化操作,當(dāng)兩個線程交錯運行的時候,很容易發(fā)生結(jié)果的丟失。因此最后的結(jié)果肯定是要小于20000的。這種情況有種專有名詞,叫race condition。

為了解決這個問題,我們可以加鎖。

#include <pthread.h>
int s = 0;
pthread_mutex_t lock;	//鎖的聲明
void *func(void *args){int i;for(i = 0; i < 10000; i++){	//給臨界區(qū)代碼加鎖實現(xiàn)原子化操作pthread_mutex_lock(&lock);s++;pthread_mutex_unlock(&lock);}return NULL;
}
int main(){pthread_t th1;pthread_t th2;//鎖初始化pthread_mutex_init(&lock, NULL);pthread_create(&th1, NULL, func, NULL);pthread_createe(&th2, NULL, func, NULL);pthread_join(th1, NULL);pthread_join(th2, NULL);printf("s = %d\n, s);return 0;
}

改進后的代碼如下,學(xué)過操作系統(tǒng)會很好理解,無非就是為了保證共享內(nèi)存區(qū)(臨界區(qū))的原子化操作,我們可以在進這段代碼之前加鎖(pthread_mutex_lock),意味著其他線程看到這段內(nèi)存被其他人占有的時候,就不去搶占,等這段內(nèi)存被解鎖(pthread_mutex_unlock)之后,它才有讀寫這段臨界區(qū)的權(quán)利。

但其實這種方式的執(zhí)行速度并不快,比如這段代碼里,每個線程都要進行10000次加解鎖的操作,它能解決內(nèi)存讀寫沖突的問題,但是卻犧牲了效率。
鎖的作用是什么呢?

前面說過多線程是并發(fā)執(zhí)行的,th1運行后 進行了加鎖,th2這時候想要運行,就必須等待th1解鎖之后才行。
(一個衛(wèi)生間,多個人要用,第一個人進去之后,把門鎖上了,后邊的人就得排隊等著,第一個方便完了,解鎖開門出來,第二個人進去,繼續(xù)鎖門……)

鎖 在提高程序的安全性的同時,也降低了程序的效率。

鎖的使用方法

pthread_mutex_t lock; 聲明一個鎖

pthread_mutex_init(&lock,NULL); 對聲明的鎖進行初始化

pthread_mutex_lock(&lock); //上鎖 此時其他線程就開始等待

pthread_mutex_lock(&unlock); //解鎖 其他線程可以使用資源了

死鎖

拿上邊舉例,th1運行后,th2會等待th1解鎖,才能運行,如果程序出現(xiàn)錯誤中斷了,th1沒有執(zhí)行完,重新啟動后,th1又重新執(zhí)行,這時候th2排在th1前邊,需要等待th1的解鎖 ,而th1又在等待th2結(jié)束。 這樣就造成了相互等待的情況,這個就是死鎖。

互斥鎖機制

通過訪問時對共享資源加鎖的方法,防止多個線程同時訪問共享資源。鎖有兩種狀態(tài):未上鎖和已上鎖。在訪問共享資源時,進行上鎖,在訪問結(jié)束后,進行解鎖。若在訪問時,共享資源已被其它線程鎖住了,則進入堵塞狀態(tài)等待該線程釋放鎖再繼續(xù)下一步的執(zhí)行。這種鎖我們稱為互斥鎖。

互斥鎖相關(guān)函數(shù)介紹:

1、pthread_mutex_init :初始化一個互斥鎖。

函數(shù)原型:int pthread_mutex_init(pthread_mutex_tmutex,constpthread_mutexattr_tattr);

2、pthread_mutex_lock:若所訪問的資源未上鎖,則進行l(wèi)ock,否則進入堵塞狀態(tài)。

函數(shù)原型:intpthread_mutex_lock(pthread_mutex_t*mutex);

3、pthread_mutex_unlock:對互斥鎖進行解鎖。

函數(shù)原型:intpthread_mutex_unlock(pthread_mutex_t*mutex);

4、pthread_mutex_destroy:銷毀一個互斥鎖。

函數(shù)原型:intpthread_mutex_destroy(pthread_mutex_t*mutex);

生產(chǎn)者消費者模型

生產(chǎn)者和消費者在同一時間段內(nèi)共用同一個存儲空間,生產(chǎn)者往存儲空間中生成產(chǎn)品,消費者從存儲空間中取走產(chǎn)品。當(dāng)存儲空間為空時,消費者阻塞;當(dāng)存儲空間滿時,生產(chǎn)者阻塞。(下面代碼中存儲空間為1)

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>int buf = 0;pthread_mutex_t mut;
void producer(){while(1){pthread_mutex_lock(&mut);if(buf == 0){buf = 1;printf("produced an item.\n");sleep(1);}pthread_mutex_unlock(&mut);}
}
void consumer(){while(1){pthread_mutex_lock(&mut);if(buf == 1){buf = 0;printf("consumed an item.\n");sleep(1);}pthread_mutex_unlock(&mut);}
}int main(void){pthread_t thread1,thread2;pthread_mutex_init(&mut,NULL);pthread_create(&thread1,NULL,&producer,NULL);consumer(&buf);pthread_mutex_destroy(&mut);return 0;
}

從執(zhí)行結(jié)果可以看出,運行順序井然有序。生產(chǎn)后必是消費,消費完后必是生產(chǎn)。由于互斥鎖機制的存在,生產(chǎn)者和消費者不會同時對共享資源進行訪問。

信號量機制

上面了解到的互斥鎖有兩種狀態(tài):資源為0和1的狀態(tài)。當(dāng)我們所擁有的資源大于1時,可以采用信號量機制。在信號量機制中,我們有n個資源(n>0)。在訪問資源時,若n>=1,則可以訪問,同時信號量-1,否則堵塞等待直到n>=1。其實互斥鎖可以看出信號量的一種特殊情況(n=1)。

信號量相關(guān)函數(shù)的介紹:
頭文件:semaphore.h
1、sem_init函數(shù):初始化一個信號量。
函數(shù)原型:int sem_init(sem_t* sem, int pshared, unsigned int value);
參數(shù):sem:指定了要初始化的信號量的地址;pshared:如果其值為0,就表示信號量是當(dāng)前進程的局部信號量,否則信號量就可以在多個進程間共享;value:指定了信號量的初始值;返回值:成功=>0 , 失敗=> -12、 sem_post函數(shù):信號量的值加1,如果加1后值大于0:等待信號量的值變?yōu)榇笥?span id="ieo6y2aa"    class="token number">0的進程或線程被喚醒。
函數(shù)原型:int sem_post(sem_t* sem);
返回值:成功=>0 , 失敗=> -13、sem_wait函數(shù):信號量的減1操作。如果當(dāng)前信號量的值大于0,則可繼續(xù)執(zhí)行。如果當(dāng)前信號量的值等于0,則會堵塞,直到信號量的值大于0.
函數(shù)原型:int sem_wait(sem_t* sem);
返回值:成功=>0 , 失敗=> -14、sem_destroy函數(shù):銷毀一個信號量。
函數(shù)原型:int sem_destroy(sem_t* sem);
返回值:成功=>0 , 失敗=> -15、sem_getvalue函數(shù):獲取信號量中的值。
函數(shù)原型:int sem_getvalue(sem_t* sem, int* sval);
獲取信號量的值,并放在&sval上。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>sem_t npro; //還可以生產(chǎn)多少
sem_t ncon; //還可以消費多少void* producer(void* arg){while(1){int num;sem_wait(&npro); //先判斷是否可以生產(chǎn)sem_post(&ncon); //生產(chǎn)一個,可消費數(shù)+1sem_getvalue(&ncon,&num);printf("produce one,now have %d items.\n",num);sleep(0.7);}
}void consumer(void* arg){while(1){int num;sem_wait(&ncon); //判斷是否可以消費sem_post(&npro); //消費一個,可生產(chǎn)數(shù)+1sem_getvalue(&ncon,&num);printf("consume one,now have %d items.\n",num);sleep(1);}
}int main(void){pthread_t thread1,thread2;//init semaphoresem_init(&npro,0,5); //設(shè)最大容量為5sem_init(&ncon,0,0);pthread_create(&thread1,NULL,&producer,NULL);consumer(NULL);return 0;
}

同樣也可以解決條件競爭問題,而且使用范圍更廣了。

解決:

  • pthread_join()函數(shù)
  • 互斥鎖機制
  • 信號量機制
http://m.aloenet.com.cn/news/28926.html

相關(guān)文章:

  • 昆山做網(wǎng)站哪家好百度競價排名廣告定價鮮花
  • 做網(wǎng)站用什么軟件知乎google瀏覽器下載
  • 企業(yè)做定制網(wǎng)站的好處自助建站免費建站平臺
  • 網(wǎng)站出現(xiàn)的的問題軟文營銷案例
  • 泰安網(wǎng)站制作seo海外
  • 做電池的外貿(mào)網(wǎng)站廣州日新增51萬人
  • 哪個網(wǎng)站不花錢可以做招聘互聯(lián)網(wǎng)營銷的特點
  • wordpress下載器插件廣東seo價格是多少錢
  • 網(wǎng)站建設(shè) 日志免費外鏈網(wǎng)
  • 做網(wǎng)站可以在哪兒接活app推廣拉新接單平臺
  • 梅州專業(yè)網(wǎng)站建設(shè)教程高端品牌網(wǎng)站建設(shè)
  • flash網(wǎng)站的優(yōu)勢廈門谷歌seo公司
  • 自己做的網(wǎng)站怎么弄成app中國聯(lián)通騰訊
  • 企業(yè)營銷網(wǎng)站福建網(wǎng)絡(luò)seo關(guān)鍵詞優(yōu)化教程
  • 網(wǎng)站頁面的滑動怎么做現(xiàn)代營銷手段有哪些
  • 購物網(wǎng)站補貨提醒軟件怎么做重慶網(wǎng)站seo診斷
  • app開發(fā)企業(yè)網(wǎng)站建設(shè)seo專員是什么意思
  • 如何設(shè)置網(wǎng)站的默認(rèn)頁網(wǎng)站模板哪里好
  • 沈陽手機網(wǎng)站制作seo課程培訓(xùn)視頻
  • 房產(chǎn)網(wǎng)站開發(fā)功能報價合肥百度關(guān)鍵詞推廣
  • 網(wǎng)站建設(shè)功能需求廣告投放價目表
  • 申請域名需要多久seo鏈接優(yōu)化建議
  • wordpress評論調(diào)用標(biāo)簽常德seo公司
  • 西鄉(xiāng)做網(wǎng)站刷贊業(yè)務(wù)推廣網(wǎng)站
  • 網(wǎng)站 租用服務(wù)器價格網(wǎng)店運營是做什么的
  • 青島市網(wǎng)站建設(shè)公司技能培訓(xùn)班有哪些
  • facebook做網(wǎng)站推廣批量優(yōu)化網(wǎng)站軟件
  • vba可以做網(wǎng)站自動填海外廣告投放公司
  • 進入網(wǎng)站服務(wù)器怎么做推廣有什么好方法
  • 電子商務(wù)seo是指什么意思seo是哪個英文的簡寫