《Programming in Lua 3》讀書筆記(二十七),programminginlua
日期:2014.8.14PartⅣ The C API
31 Threads and States Lua實際上是不支援真正的多線程的,即preemptive threads 共用記憶體的情況。有兩個原因:第一個,是ANSI C不支援,所以Lua中就沒有合適的方法來實現這個機制;第二個原因,最重要的是作者認為Lua中支援真正的多線程不是個好主意。 多線程是給低級開發語言而發展出的機制。多線程概念中的訊號和監控等同步機制機制都是依賴與作業系統而不是依賴於應用程式的,因此很難去發現和修正由多線程造成的bug,而且這些bug中的一些可能會造成安全問題。不僅如此,多線程也可能會對程式運行過程由於需要做資訊同步而造成效能影響,如影響程式的記憶體配置。 由多線程帶來的問題主要是從preemptive thread 和 記憶體共用結合 中產生的,因此Lua中通過使用 non-preemptive thread 和不共用記憶體來避免這些問題。Lua的線程(也叫協同程式)是協作的,因此避免了由不可預期的線程切換所帶來的問題,且Lua的State是不共用記憶體的,因此在為並發性提供了一個良好基礎。這一章主要是講這個兩點。
31.1 Multiple Threads Lua中的線程本質上是一個協同程式。我們可以認為一個協同程式就是一個線程加上一個良好的介面,或者我們可以認為一個線程就是帶一個低等級API的協同程式。 從C API角度來看,認為一個線程就是一個棧是挺有用的。而從實現過程角度來看,線程確實是一個棧。每個棧儲存所有未執行的調用、每次調用的參數和局部變數等資訊,換句話來說一個棧擁有一個線程要準備再次啟動並執行所有資訊。因此,多線程就是意味著多個獨立的棧。 實際上看,我們之前討論的各個Lua-C 的API函數,都是在一個特定的棧上操作的,這個從一開始就知道了。但是我們又是如何知道我們要操作具體的哪個棧呢?會不會操作錯了?這裡關鍵點就在於我們每次調用函數時的第一個參數類型lua_State ,這個參數不僅代表一個lua state,也同時包括在這個state中的thread。 無論何時建立了一個Lua state,Lua都會自動在這個state中建立一個新的線程,然後返回一個代表這個線程的lua_State。這個主線程是從不會被回收的(這個??是否指的除去調用lua_newthread額外建立的這些線程,即建立lua state自動建立的這個線程)。當你用lua_close 關閉了這個state的時候,線程會隨同state一起釋放。 可以在一個state中通過調用lua_newthread 來建立另外的thread:
lua_State *lua_newthread(lua_State *L);
上面這個函數返回一個代表這個新線程的lua_State 型指標,並且同時將這個新的線程作為thread類型推進棧中,如:
L1 = lua_newthread(L);
經過上面這步,我們就有了兩個線程了,且兩個線程都實際上在同一個lua state內部。每個線程都有自己獨立的棧,新的線程L1有個空的棧;而L線程則將新的線程儲存在其自身棧的棧頂。如:
e.g.printf("%d\n",lua_gettop(L1)); --0 新的線程的棧是一個空的棧printf("%s\n",luaL_typename(L,-1)); --thread 代表在棧頂是一個線程,即新的那個線程 除了主線程之外,其餘的這些線程都是受garbage collection管理的對象,和Lua其餘的這些對象一樣。當建立了一個新的線程,以thread類型將這個線程推進至棧中,保證了這個線程不會被回收掉。我們應該確保不使用那些不確定還是否在棧中的線程。每次調用Lua的API都可能會觸發回收那些不在棧中的線程,即便這個線程還在使用中,如:
lua_State *L1 = lua_newthread(L);lua_pop(L,1); /* L1 is garbage*/lua_pushstring(L1,"helloe"); /* danger */
調用lua_pushstring的時候可能會觸發garbage collector回收掉L1,即便此時仍然在使用這個線程。為了避免遇到不可預期的錯誤,應該始終對我們在使用中的線程保持引用,for instance in the stack of an anchored thread or in the registry. 新建立的線程,可以和使用主線程一樣使用。可以從該線程的棧中推進和推出元素,可以使用棧來調用函數等等。這裡介紹一個函數lua_xmove(L1,L,1),這個函數的作用是做同一個state中的棧的資料移動,如lua_xmove(F,T,n),就是從棧F中推出一個 元素,然後推進至棧T中。做這個操作我們甚至都不需要建立額外新的線程,只需要在主線程中處理就可以了。在這裡使用多線程的前提是實現協同程式,以便我們可以延緩或者恢複某個線程的執行。恢複執行某個函數,在這裡就需要函數:lua_resume 來支援:int lua_resume(lua_State *L,lua_State *from ,int nary); 如我們使用lua_pcall 一樣,如果我們想運行一個協同程式,我們可以使用lua_resume函數:將要調用的函數,參數推進至棧中,函數參數narg代表傳遞的參數的數量。(from 參數指的是執行這個調用的線程所在的state)。主要的行為類似於lua_pcall,但還是有三個不同的地方:1、lua_resume沒有代表返回值數量的參數,函數總是會返回所有的返回結果;2、沒有給訊息控制代碼用的參數,錯誤不會在棧中觸發,因此可以在錯誤之後檢測棧(~~~沒看懂);3、如果在啟動並執行這個程式被掛起了,lua_resume 返回一個特殊代碼:LUA_YIELD ,且將在state中的線程保留下來留給之後重新調用。 協同程式也能調用C函數,這些C函數也能回調其他的Lua函數。
31.2 Lua State 每次調用luaL_newstate函數將會建立一個新的lua state.不同的Lua state相互之間是獨立的,這就意味著一個state內部的事件是不會對其他的state產生影響的,也意味著不能在state間直接進行資料互動,而是需要藉助C代碼。如:lua_pushstring(L2,lua_tostring(L1,-1); 上述代碼將L1棧頂的元素藉助C API傳遞到了L2中。因為我們是需要藉助C API來實現資料互動的,所以傳遞的資料類型必須是C所支援的類型,像table之類的資料需要藉助合適的方式首先進行轉換才可以傳遞。 在支援多線程的系統中,為每個線程建立獨立的Lua state這個結構值得去探討一番。這個結構的結果類似與UNIX中的processes,在這裡我們可以不shared memory就可以得到並發性。 這個小節剩下的部分是作者介紹他用POSIX 線程實現上述提到的為每個線程建立獨立的Lua state,感覺有點難懂,就不再筆記了。留給以後再深入理解一番。
讀書筆記 《XXXXXXX》 1摘抄(雅詞佳句) 2品讀(關鍵句段) 3感悟(全片啟迪) 要5篇一定要按照要哦
一千零一夜 讀書筆記
《一千零一夜》是世界各國人民熟知的阿拉伯經典文學作品。大型舞劇《一千零一夜》便向觀眾講述了這部傑作充滿夢幻的誕生過程,而關於這個過程的故事在全世界已經是婦孺皆知:古時候,薩桑王國的國王山努亞因妻子背叛了他而萬分仇恨女人。因此,他每晚娶一個女人過夜後便殺掉。三年後,宰相的女兒大膽入宮,並每晚給國王講一個故事,在天亮時便停下來,第二天接著講。經過1001個夜晚,國王終於打消了殺女人的心思,世界名著《一千零一夜》也由此誕生。》一千零一夜》是我非常喜歡讀的書,《一千零一夜》又叫做《天方夜譚》,《一千零一夜》裡面有好多非常古怪的故事,有《山魯亞爾和山魯左德》、《漁夫和魔鬼的故事》、《漁夫和四色魚的故事》、《著摸王子的故事》、《白侯圖的故事》等等,這裡有幽默的、悲哀的、有趣的、可怕的、悲慘地種種故事,我覺得這《一千零一夜》裡的故事有好有不好,比如說《漁夫朱德爾的奇遇》就屬於不好,朱德爾是靠力量和運氣來獲得幸福的,但《阿拉丁神燈》就是屬於好一類裡的,因為阿拉丁靠的是一顆不氣餒、勇敢的一顆心來奪得幸福的。莎拉《一千零一夜》的故事要從阿拉伯講起,故事中,女主人公莎拉對各國民歌和異域風光情有獨鐘。就像中東熱情的沙漠一樣,莎拉也將自己熱情的歌聲散播到四方,對於莎拉來說,好故事一定要有聽眾一起分享,充滿創意的獨特構思、舉世無雙的天籟歌聲,從《一千零一夜》裡走來的莎拉,這就要把她的故事帶到中國上海,看這位“月光女神”如何續寫這段美麗的神話。
讀《永別了武器》讀書筆記
一個告別了武器的人,不是敵人的俘虜,就是愛的俘虜.我不是不善於自我保護,實在是一個放棄自我保護的人.就如同生命的資料庫,已經不需要進入的密碼,隨時都可以開啟全部程式,可以讀出全部的檔案.我說的俘虜,就是這個意義上的俘虜.當我把自我放到陽光下的時侯,我明白從此不能有所偽裝,隱形日子一想起就令人不安.當我意識到抗拒的無奈,有多少時間無可挽回,有多少記憶漸漸從內心淡出.說到底,俘虜就是一個不能抵擋傷害的人,就是要有足夠的勇氣放棄希望,必須承受生存的全部壓力.本來,在屬於個人的空間,可以沉浸於獨自的幻想,可以從塵埃裡開出虛擬花朵.而一個放棄自我保護的人是連欺騙自己都不能,只有不斷地淨化內心世界.
《哈姆雷特》讀書筆記
莎翁的《哈姆雷特》是一部經典的代表作.這本書在表面情節上與曆史的傳說並沒有多大的區別,講的還是丹麥王子為父報仇的故事,其中充滿了血腥暴力和死亡.正如
劇中人霍拉旭所說: 你們可以聽到姦淫殘殺,反常修理的行為,冥冥中的判決,意外的屠戮,藉手殺人的狡計,以及陷入自害的結局. 曲折選宕的情節,緊緊圍繞著複仇
而展開.哈姆雷特從德國的威登堡匆匆趕回國內,是來參加他父親的葬禮的,使他不能接受的是,他未趕上父親的葬禮,卻目睹了母親與叔叔克勞迪斯的婚禮,這已使哈姆萊特疑竇在心,加之夜晚在王宮城堡的露台上與父親的亡魂相見,亡魂哀訴,這樁暴行是哈姆雷特的叔叔所為,並要他為父報仇.至此,他開始了艱難的複仇曆程,與克勞迪斯展開了你死我活的較量.最終,向克勞迪斯發出了複仇之劍.
《基督山伯爵》讀書筆記
愛也徹底,恨也徹底.報恩也徹底,複仇也徹底.這就是在我讀完《基督山複仇記》後最大的感受.中國有句俗語叫做君子報仇,十年不晚,報仇也是需要養精蓄銳的,並不是憑著一時的心緒就可輕舉妄動的.而基督山伯爵,則是最具體的用自己的行動闡釋了這句俗語的.在經曆十四年的地牢生涯後,他的人生要義就是找尋曾經的親人,曾經的恩人和曾經的仇人.在確認了所要尋找的人以後,他並沒有如我們在武俠小說裡所見的......餘下全文>>
讀書筆記10篇
《童年》 高爾基
好詞摘錄:
忽如其來、飄忽、興趣盎然、熠熠生輝
好句摘錄:
伏爾加河藍色的水面上,桔紅色的輪船在逆流而上,而一張張金色的葉片則緩緩順流漂下。
我非常害怕外祖父,總覺得他的綠眼珠無時無刻不在盯著我看。
那曲子激昂中含著憂傷,彷彿是從高山奔流而下的河水,激蕩在房間中。
經常有人聽見了他們的歌聲從窗戶底下停下來看著他們,那一張張仰起的面孔讓我想起沒洗的髒盤子。
好段摘錄:
“唉,你們這些人啊……!”他常常這樣忽如其來地歎氣,也不知在感歎什麼。“人啊……”的尾音總是被他拉得長長的。
茨岡臉色紅紅地走到廚房中間,像一團火焰般地跳動起來:兩手高高揚起,腳步快得讓人難以分辨,襯衫抖動著,像燃燒一般發出燦爛地光輝。他放縱地舞著,彷彿開啟門讓他出去他就能跳遍全城!大家都被他感染,跟著他顫動起來。
歌唱中,外祖母時而前進,時而後退,時而飛旋,青春瞬間回到了她的身上,令她呈現出一種鮮花綻放般的美麗。每個人都被她吸引住了。
我的感想:
作者將主人公當時所處的骯髒的環境寫得很到位,在語言描寫上很有功夫。使文章生動,令人身臨其境,對美與醜及人複雜的感情有了更深層次的瞭解。
魯濱遜飄流記》中的好詞好句好段
好詞摘錄:
擱淺、兜底、吞噬、煙波瀰漫、泅水、山坳、恭順、驚魂甫定、斑斑印記
好句摘錄:
我簡直嚇壞了,獃獃地佔在那裡,就象挨了一個晴天霹靂。
看到這情景,我怒不可遏,早把恐懼置之度外。我在心裡發誓:下次再看到這種暴行,一定不放過他們!
好段摘錄:
這裡地上結滿了許多瓜類,樹上掛滿了一串串的葡萄,有數有大,還有黃燦燦的檸檬。我順著果園的斜坡望去,到處是一片清新翠綠的美景,這是我心裡充滿了喜悅,頓時感到自己成了這塊富饒的土地的無可爭辯的主人。
1. 開始做一件事的時候,若不是預先計算一下需要多少代價,若不是預先對自己的力量做一個正確的估計,那真是太愚蠢了。
讀《魯濱遜漂流記》有感
全篇著重描寫了魯濱遜在荒島上通過自己的勞動克服重重困難,最終戰勝了惡劣的環境,與土著人星期五共同回到了家鄉,過上了幸福生活的故事。
我最欣賞的不是魯濱遜的勤勞與勇敢,而是他那驚人的心理承受能力。可想而知,一個孤零零的大活人獨自在荒島上生活了十幾年,沒有人陪伴他,甚至於最基本的,與一個人簡簡單單地說會兒話都做不到。整個荒蕪的島上沒有房屋,沒有稻田,只能靠他自己辛辛苦苦地打造出一片天地
昆蟲記之七—— 裝死專家步甲 作者 法布爾
優美詞語
引以為傲、不屑一顧、恭敬、火冒三丈、攻勢、、逃之夭夭、得意洋洋、苦澀、僥倖、惟恐、履行、自言自語、伎倆、威懾、荒謬、唯唯諾諾、喧鬧、一言不發、膽怯、挺身而出、毫不畏懼、暈厥、火勢、千姿百態、愚蠢、卑鄙、虐待、毛骨悚然、筋疲力盡、昏迷不醒、蜷縮、憐憫、憤怒、難以忍受、爭先恐後
精彩句段
我們不知道什麼叫死亡,所以我們不會做出裝死的行為!不管遭受什麼樣的虐待,我們始終是正直的昆蟲,絕對不會做出欺騙他人的行為。
別說是因為我們不會飛,才想出裝死的伎倆!別說是因為我們跑不快,才想出裝死的伎倆!我們根本不知道什麼是死亡,所以不會做出裝死的行為!
尤其是自殺,連想都沒有想過!那種愚蠢的事情,只有卑鄙的人才會做出來!
讀後有感
強者也會偶爾的躲避著比自己厲害的對手,以免的丟掉自己的性命。作者 對步甲昆蟲的瞭解很透徹,步甲蟲裝死是它抵禦不了對方時的一種自衛的方式,孩子,在這個世界上無論是人類還是其他動物就像本書中敘述......餘下全文>>