中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

如何用源代碼做網(wǎng)站手機優(yōu)化什么意思

如何用源代碼做網(wǎng)站,手機優(yōu)化什么意思,在線p圖網(wǎng)頁,第一次做ppt怎么弄上一期我們進行了線程控制的了解與相關(guān)操作,但是仍舊有一些問題沒有解決 本章第一階段就是解決tid的問題,第二階段是進行模擬一個簡易線程庫(為了加深對于C庫封裝linux原生線程的理解),第三階段就是互斥。 目錄 線程id…

上一期我們進行了線程控制的了解與相關(guān)操作,但是仍舊有一些問題沒有解決在這里插入圖片描述
本章第一階段就是解決tid的問題,第二階段是進行模擬一個簡易線程庫(為了加深對于C++庫封裝linux原生線程的理解),第三階段就是互斥。

目錄

  • 線程id:
    • LWP與tid:
    • 動態(tài)庫的加載:
    • 線程id:
    • 如何理解維護在庫中:
    • 再次感受一下pthread_join():
    • 線程局部存儲:
  • 封裝線程庫:
    • 封裝:
  • 互斥:

線程id:

LWP與tid:

我們還是先來寫一段簡單的代碼進行驗證一下LWP與線程id的關(guān)系。

代碼:
在這里插入圖片描述
驗證結(jié)果:在這里插入圖片描述

在這里插入圖片描述
足以觀察到LWP與tid的差距是非常大的。

這說明給用戶提供的線程id并不是內(nèi)核中的LWP,而是自己維護的一個唯一值。
自己就是pthread庫。

雖然剛開始覺得不符合常理,但仔細想一想而本該如此:
因為linux并沒有線程,但是我們用戶需要線程的概念,所以pthread庫充當了一個中間角色,封裝linux中的輕量級進程,因此,并不需要呈現(xiàn)給用戶LWP的值,給用戶呈現(xiàn)自己封裝的線程id即可。就像C語言中的FILE,我們直接用庫封裝好的,并不需要在使用文件描述符fd了,也不需要展現(xiàn)給用戶。

因為庫提供了線程id,所以庫也要對pthread進行管理,怎么理解呢?
可以理解為學校給你提供了學號,所以學校要對你進行管理。

我們的linux肯定提供了輕量級進程的調(diào)度系統(tǒng)調(diào)用,但是一個線程不僅僅需要被調(diào)度,也需要一個id,棧大小,被誰啟動…這些屬性也是由庫做管理的!

針對管理我們要展開一下。

動態(tài)庫的加載:

那就要先看一下線程庫的加載,首先動態(tài)庫和我們的程序肯定都是在磁盤上的文件。
在這里插入圖片描述

當我們./運行時,會建立內(nèi)核數(shù)據(jù)結(jié)構(gòu) + 加載數(shù)據(jù)與代碼。

在這里插入圖片描述
當我們執(zhí)行到pthread_create時,因為我們還未加載動態(tài)庫,會觸發(fā)缺頁中斷,去加載動態(tài)庫,再將動態(tài)庫映射到共享區(qū)。
在這里插入圖片描述
此時我們就可以正常去執(zhí)行我們的pthread_create去創(chuàng)建線程了。

而我們也說過庫需要對我們的線程id,棧的大小…進行維護,也就是進行管理

而管理就需要對該對象進行描述再進行組織,下圖就是描述他的結(jié)構(gòu)體pthread_t。在這里插入圖片描述
其中的struct pthread是用戶最基本的線程屬性,線程局部存儲我們稍后再來進行講解。而編程棧就是我們常說的每個線程都有一個獨立的線程棧!

組織我們可以看成是使用一個數(shù)組進行組織起來的。

線程id:

所以以后想找線程屬性,擁有地址即可進行管理,而我們的tid就是相應(yīng)的pthread_t的地址。

如何理解維護在庫中:

我們還是以FILE進行舉例。
我們的FILE是一個結(jié)構(gòu)體:

struct FILE
{int fd;char buff[N];...
}

我們打開一個文件會得到一個FILE的指針。

而這個FILE結(jié)構(gòu)體指針就維護在標準庫中,進入這個函數(shù)時,會執(zhí)行malloc(sizeof(struct FILE))類似的代碼在堆上申請空間,等執(zhí)行完之后返回給用戶FILE*,讓用戶進行操控。所以我們也就可以理解維護在庫中了。

就像我們使用STL中的各種容器,不需要管底層是如何擴容的。

再次感受一下pthread_join():

在這里插入圖片描述
所以我們也就理解了pthread_create時的attr在這里插入圖片描述
這就是用來控制pthread_t的屬性,比如控制棧的大小…

總結(jié):linux線程 = pthread庫 + LWP,其中內(nèi)核維護的LWP與動態(tài)庫中維護的線程是1:1的。

但是同學們,我們該如何保障新線程輕量級進程會使用你指定的棧?
因為我們的輕量級進程中有一個系統(tǒng)調(diào)用:clone。
在這里插入圖片描述
第一個是回調(diào)函數(shù),第二個就是指定的棧,第三個是參數(shù),所以pthread庫本質(zhì)就是對這樣的一堆系統(tǒng)調(diào)用進行封裝。

線程局部存儲:

現(xiàn)在還剩最后一個問題,線程局部存儲是啥?在這里插入圖片描述
我們先來看這樣一段代碼:
搞一個全局變量,新線程改,主線程讀取。
在這里插入圖片描述

現(xiàn)象: 一改具改,符合預期。

但是如果我們想要互相不影響,也就是新主線程雖然用同一個全局變量名字,但是實際卻是兩個地址。
我們可以加入編譯選項__thread
注意:這個只可以修飾全局的內(nèi)置類型。

在這里插入圖片描述

現(xiàn)象:可以看到虛擬地址也不相同。
在這里插入圖片描述
結(jié)論:雖然看起來還是用一個,但實際上各自私有一份

封裝線程庫:

本質(zhì)是為了更好的理解C++11是如何進行封裝的。

我們的目標是實現(xiàn)如下幾個接口:
在這里插入圖片描述
也可以在來一個GetStatus,調(diào)用可以觀察到此線程是否正在運行。

封裝:

在這里插入圖片描述
先來解釋一下成員變量,_name就是線程名字,_tid是線程id,_func是用戶傳遞來的要執(zhí)行的函數(shù),_isRunning是代表當前線程是否在運行。


在實現(xiàn)時有兩個的坑點。
其一:因為我們是進行封裝,所以是在類中實現(xiàn)。
但是我們將routine寫出了之后卻找不到對應(yīng)routine,這是因為類中的成員默認有隱含的this指針,所以參數(shù)的個數(shù)就不匹配了。
在這里插入圖片描述
解決這種問題的辦法很多,但我們最喜歡用static進行修飾,這樣就不會有this指針了,這個函數(shù)屬于整個類。
在這里插入圖片描述
可是這樣我們就無法訪問類中的成員變量了,因為沒有this指針~

那怎么辦?
把this指針當做參數(shù)傳給routine!

在這里插入圖片描述
這樣就可以調(diào)用外部給我們傳的指定函數(shù)了。
可是這樣調(diào)用未免有些丑陋。
在這里插入圖片描述
在將stop,join進行填補即可,注意,我們的構(gòu)造函數(shù)需要一個你指定的名字和待執(zhí)行函數(shù)。

主函數(shù)代碼:
在這里插入圖片描述
現(xiàn)象:

在這里插入圖片描述
也是完成了我們預期的工作。

源代碼:

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdio>namespace cyc
{class mythread{public:typedef void (*func_t)(std::string);mythread(const std::string &name, func_t func) : _name(name), _func(func), _isRunning(false){}~mythread(){}void Excute(){_isRunning = true;_func(_name);_isRunning = false;}static void *routine(void *arg){mythread *self = static_cast<mythread *>(arg);self->Excute();return nullptr;}void Start(){int n = ::pthread_create(&_tid, nullptr, routine, (void *)this);if (n != 0){perror("pthread_create fail");exit(1);}}void Stop(){if (_isRunning){pthread_cancel(_tid);_isRunning = false;}}void Join(){int n = pthread_join(_tid, nullptr);if (n != 0){perror("pthread_join fail");exit(1);}}std::string GetStatus(){if(_isRunning) return "Running";else return "sleeping";}private:std::string _name;pthread_t _tid;func_t _func;bool _isRunning;};
}

于是我們就完成了一個很簡易的封裝~

互斥:

多個線程能夠看到的資源叫做共享資源。
但是也會有一些問題,比如我們線程通信,一個線程想寫hello world,但是剛寫了hello就被另一個進程獨走了,叫做讀寫不一致,
所以我們需要對共享資源做保護。

其中最簡單的方法是互斥。

但是我們總要先見一見吧。
我們模擬一個搶票的代碼,假設(shè)一共有1w張票,創(chuàng)建4哥線程同時去搶,每搶一次記錄一下?lián)屩暗钠睌?shù),當票數(shù)<=0就是出現(xiàn)了問題。

我們就是用剛剛模擬實現(xiàn)的線程進行操作。
代碼:
在這里插入圖片描述
現(xiàn)象:
在這里插入圖片描述
果然出現(xiàn)了0甚至負數(shù),這就證明我們的搶票提供非常的失敗~

可是原理是什么呢?

首先我們要有兩個儲備知識。
其一是判斷也是一種運算,為邏輯運算。
一共有兩種運算,分別為算術(shù)運算與邏輯運算,簡稱算羅運算。

其二是線程的切換,CPU內(nèi)寄存器只有一套,但是擁有的數(shù)據(jù)有多套。切換時帶走自己的數(shù)據(jù),回來時會回復!

對于1來說,邏輯判斷至少分為3步,雖然語法上表現(xiàn)為3步,但是實際轉(zhuǎn)換到匯編有2-3步。在這里插入圖片描述
我們假設(shè)線程1在還有最后一張票時進入,已經(jīng)判斷完畢了,但是此時tickets還沒進行--,這時時間片到了,線程1被切換,帶走了當前寄存器的值與記錄執(zhí)行到的語句。同理2,3,4也都分別執(zhí)行完判斷語句就被切換這就有很大的問題了。

因為只有一張票卻有4個線程進入了,等線程a,b,c,d分別恢復時將數(shù)據(jù)又放回到寄存器中。
注意:進行--時需要將數(shù)據(jù)重讀,修改,在放回內(nèi)存中這三步

所以票數(shù)就變?yōu)?,-1,-2…

下章繼續(xù)~

http://www.risenshineclean.com/news/53293.html

相關(guān)文章:

  • 微信網(wǎng)頁宣傳網(wǎng)站怎么做的百度搜索關(guān)鍵詞技巧
  • 自己做網(wǎng)站制作流程免費網(wǎng)站推廣軟件
  • 做青蛙網(wǎng)站做網(wǎng)站怎么賺錢
  • 響應(yīng)式布局代碼怎么寫名詞解釋搜索引擎優(yōu)化
  • 一個網(wǎng)站推廣武漢新一輪疫情
  • 新開傳奇手游網(wǎng)站大全網(wǎng)站seo關(guān)鍵詞
  • 政府網(wǎng)站建設(shè)出現(xiàn)的問題及對策廈門百度關(guān)鍵詞seo收費
  • 網(wǎng)站上的導航欄怎么做網(wǎng)站站長工具
  • 日本人真人做真愛的免費網(wǎng)站鄭州網(wǎng)站優(yōu)化顧問
  • 電商網(wǎng)站建站開發(fā)語言seo快速建站
  • 做網(wǎng)站賺錢嗎 怎么賺今天特大新聞
  • 做寫手一般上什么網(wǎng)站好百度快照怎么用
  • 做蛋糕的網(wǎng)站科學新概念外鏈平臺
  • 小兔自助建站廣州排名推廣
  • 建設(shè)銀行網(wǎng)站用360瀏覽器關(guān)鍵詞seo是什么
  • 建設(shè)部監(jiān)理工程師考試網(wǎng)站怎么給自己的公司做網(wǎng)站
  • 成品網(wǎng)站整套源碼如何做好營銷推廣
  • 嘉興做美食圖片的網(wǎng)站南和網(wǎng)站seo
  • 網(wǎng)站建設(shè)專業(yè)性競價賬戶托管公司
  • 網(wǎng)站開發(fā)助理好嗎外貿(mào)網(wǎng)站推廣優(yōu)化
  • 如何讓單位網(wǎng)站做防護十句經(jīng)典廣告語
  • 百中搜網(wǎng)站建設(shè)百度我的訂單
  • 個人建網(wǎng)站今日頭條關(guān)鍵詞排名優(yōu)化
  • 外貿(mào)網(wǎng)站運營怎么做百度手機端排名如何優(yōu)化
  • 濟寧萬達網(wǎng)站建設(shè)合肥網(wǎng)站推廣公司
  • 主要怎么學的呢seo網(wǎng)站建設(shè)是什么意思
  • python做公司網(wǎng)站人工智能培訓心得
  • 城鄉(xiāng)建設(shè)部網(wǎng)站首頁甲級網(wǎng)站搜索優(yōu)化價格
  • 濟南網(wǎng)站建設(shè)凡科seo主要優(yōu)化
  • 安徽建設(shè)監(jiān)理協(xié)會網(wǎng)站seo有哪些網(wǎng)站