真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++線程操作-創(chuàng)新互聯(lián)

文章目錄
  • 一、線程和進程的基本概念
  • 二、C++中的線程
  • 三、互斥量mutex的使用
  • 四、條件變量condition_variable的使用
  • 五、如何獲得線程的返回值
  • 六、線程的其他使用

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比宕昌網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式宕昌網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋宕昌地區(qū)。費用合理售后完善,十多年實體公司更值得信賴。
一、線程和進程的基本概念

線程是操作系統(tǒng)進行運算調(diào)度的基本單位,進程是操作系統(tǒng)進行資源分配的基本單位。
不同進程分配不同的內(nèi)存區(qū)域,同一個進程中的不同線程共享同一片內(nèi)存。

線程的不同狀態(tài):

  1. 新建狀態(tài):僅僅是語言層面創(chuàng)建了線程狀態(tài),但是還沒有與操作系統(tǒng)線程進行關聯(lián);
  2. 就緒狀態(tài):線程已經(jīng)與操作系統(tǒng)相關聯(lián),可以被CPU進行調(diào)度;
  3. 運行狀態(tài):線程正占用著CPU,正在運算;
  4. 阻塞狀態(tài):等待被喚醒的狀態(tài);
  5. 終止狀態(tài):線程運行結束。

并行(Parallel)是真正意義上的同時運行,在同一時間點有多個程序在同時運行,比如多核CPU多個核同時運行著不同的程序。并發(fā)(ConCurrent)是在同一個時間段上多個程序同時運行,在宏觀上看是同時運行,微觀上是交替運行。

之所以設計多線程是為了充分的利用CPU資源,比如線程A正在等待磁盤數(shù)據(jù)的時候,可以將CPU讓出來,線程B就能占用CPU進行計算。

二、C++中的線程

c++11新增了與操作系統(tǒng)無關的線程類thread,使用方法如下:

void func(int i) {cout<< i<< endl;
}

int main() {thread t1(func, 10);  //傳入線程綁定的函數(shù)和函數(shù)所需參數(shù)
    t1.join();
    return 0;
}

thread對象創(chuàng)建之后,線程就已經(jīng)進入就緒態(tài),可以占用CPU進行運算。
線程的運行需要以具體的函數(shù)作為入口,而函數(shù)的參數(shù)傳遞無非值傳遞,引用傳遞和指針傳遞3種形式,值傳遞和指針傳遞沒什么好說的,直接復制值或者指針放入線程入口函數(shù)中,而線程的使用中需要特別注意??????引用傳遞,普通函數(shù)使用引用傳遞,底層使用的還是指針,所以函數(shù)中的引用會關聯(lián)到函數(shù)外的變量。但是在線程的使用中,函數(shù)引用傳遞是引用的復制,函數(shù)中的引用和函數(shù)外的值沒有關聯(lián)關系。如果想關聯(lián),必須傳遞參數(shù)的時候使用std::ref()語義進行包裹。

join()detach()的用法:調(diào)用線程的join()方法意味著,主線程會阻塞在該語句處,等待子線程運行結束的時候才會繼續(xù)運行主線程,而detach()方法意味著,子線程從主線程中分離出來各自運行,子線程變?yōu)楹笈_守護線程(deamon thread),如此這般,子線程可能會結束在主線程之后,可能會出現(xiàn)不可預知的問題。

三、互斥量mutex的使用

當存在多個線程共同訪問同一資源(比如隊列)的時候,如果操作的順序不當可能會出現(xiàn)不可預知的錯誤,該資源成為臨界資源,此時C++使用互斥量mutex進行資源訪問的控制。

通常為了方便理解多線程操作,我們將mutex稱為鎖🔒,對資源的訪問稱為對資源上鎖和解鎖。實際上mutex是一個標記量,不同的線程對同一mutex對象進行lock()unlock()可以達到控制資源訪問次序的目的。

lock()方法是嘗試獲取鎖并加鎖,如果獲取不到鎖,線程就會阻塞在此語句處,mutex調(diào)用了lock()就必須unlock(),否則就有可能是其他線程不能成功lock()而一直阻塞。
為了解決這種可能忘記unlock()的問題,引入lock_guard模版類,lock_guard類似于智能指針,出作用域會自動unlock()。和lock_guard相似的一個模版類是unique_lock,使用方法和lock_guard類似。

四、條件變量condition_variable的使用

多個線程需要通信的時候會用到cv,比如消費者和生產(chǎn)者線程模型,這兩個線程并不是單單的對資源解鎖和加鎖。而是需要通信,比如,消費者沒有資源可以消費的時候需要將生產(chǎn)者叫醒。

cv有兩個方法wait()wait_for(),wait方法會讓當前線程釋放鎖然后阻塞,直到被喚醒;wait_for方法需要傳遞一個時間參數(shù),當前線程釋放鎖然后等待被喚醒,但是不會一直等待,而是吵過時間參數(shù)自動蘇醒。
cv還有兩個方法notify_one()notify_all()notify_one會喚醒線程等待隊列的第一個線程,而notify_all會喚醒所有等待的線程。

waitsleep方法的區(qū)別:

  1. waitcv的方法,sleepthis_thread的方法;
  2. wait會釋放鎖然后再阻塞,而sleep直接阻塞,不會釋放鎖。

五、如何獲得線程的返回值

前面提到的線程入口函數(shù)都是實現(xiàn)一系列的操作但是沒有返回值,如果需要線程的返回值,我們需要使用std::future<>這樣一個模版類來接受返回值,而普通的用thread創(chuàng)建線程的方式不能獲得future對象,此時有數(shù)種方法:

  1. 使用異步任務函數(shù)std::async(),顧名思義,異步任務就是啟動一個和主線程并發(fā)的任務,該方法會返回一個future對象,通過該對象的get()方法就能獲得線程返回的對象,使用方法如下:
int func() {return 1234;
}

int main() {std::futurefval = std::async(func);
    std::cout<< fval.get()<< std::endl;
    return 0;
}

主線程會阻塞在get()處,直到線程返回返回值。async()方法還可以傳入一個枚舉標志量std::launch,如果將此標記量設置為deferred,意味著方法調(diào)用處不會立即創(chuàng)建線程,直到調(diào)用get()方法才會創(chuàng)建方法并運行,而此時和直接在主線程調(diào)用線程入口函數(shù)是一樣的,是串行運行。注意??:get()方法只能調(diào)用一次;

2. 使用std::package_task<>包裹一個函數(shù),然后傳遞給一個線程對象,線程運行起來之后用package_task對象的get_future()方法獲得future對象,然后再用get()方法拿到返回值。package_task使用方法如下:

int func() {return 1234;
}

int main() {std::packaged_tasktask(func);
    std::thread t1(std::ref(task));
    t1.join();
    std::cout<< task.get_future().get()<< std::endl;
    return 0;
}

  1. 使用std::promise<>模版類可以從線程中將值帶到線程外,promise對象會傳遞到線程入口函數(shù)中去,然后在線程運行過程中,使用set_value()方法給promise對象賦值,然后在異步線程之外,使用promise對象的get_future()方法獲得future對象,之后的操作和以上就一樣了。使用方法如下:
void func(std::promise&pro) {pro.set_value(100);
}

int main() {std::promisepro;
    std::thread t1(func, std::ref(pro));
    std::cout<< pro.get_future().get()<< std::endl;
    t1.join();  //此處使用join其實意義不大,因為get已經(jīng)獲取到值說明異步線程已經(jīng)結束
    return 0;
}

六、線程的其他使用
  1. wait被喚醒之后第一件事是會反復嘗試直到拿到鎖再往下執(zhí)行,wait被喚醒拿到鎖之后一般還要再次檢查阻塞條件保證多線程共享的正確性;
  2. unique_lock所有權的轉(zhuǎn)移類似于unique_ptr,使用move進行所有權轉(zhuǎn)移;
  3. std::lock(mutex1, mutex2)方法可以嘗試同時鎖住多個互斥量,如果有一個沒鎖成功,就不會對任何互斥量進行加鎖;
  4. release()方法將unique_lockmutex解綁,并返回之前綁定的mutex;
  5. 互斥量mutex,lock()unlock()之間包裹的語句多少稱為鎖的粒度,粒度要合適,如果太小可能不能達到上鎖的預期,如果太大,會降低多線程運行效率;
  6. std::adopt_lock可以傳遞給lock_guardunique_lock的構造函數(shù),表示這個互斥量已經(jīng)被lock了(你必須要把互斥量提前l(fā)ock了 ,否者會報異常);std::adopt_lock標記的效果就是假設調(diào)用一方已經(jīng)擁有了互斥量的所有權(已經(jīng)lock成功了);通知lock_guard不需要再構造函數(shù)中l(wèi)ock這個互斥量了。unique_lock也可以帶std::adopt_lock標記,含義相同,就是不希望再unique_lock的構造函數(shù)中l(wèi)ock這個mutex。用std::adopt_lock的前提是,自己需要先把mutexlock上;用法與lock_guard相同;
  7. std::try_to_lock會嘗試用mutex的lock去鎖定這個mutex,但如果沒有鎖定成功,也會立即返回,并不會阻塞在那里,用這個try_to_lock的前提是你自己不能先lock;
  8. std::defer_lock的前提是,你不能自己先lock,否則會報異常,std::defer_lock的意思就是并沒有給mutex加鎖,初始化了一個沒有加鎖的mutex。

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


本文名稱:C++線程操作-創(chuàng)新互聯(lián)
URL分享:http://weahome.cn/article/pcigi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部