同事代碼有個Bug困擾了他半個月,影響了項目驗收,后來實在沒辦法了,我就拿起了他的代碼開始研究,最后我竟然發(fā)現(xiàn)他代碼中一個讓人無語的地方,也正是這個地方,導(dǎo)致他的代碼始終有問題!最后,我真是不知道說什么好了!
話說,我們公司有個項目在二十多天前就已經(jīng)到了合同約定的驗收時間了,但是因為項目當(dāng)時上得比較急,所以,在驗收時間到達的時候,我們老板跟客戶好說歹說才又爭取了一個星期的延期。
當(dāng)初我認(rèn)為一個星期的時間是綽綽有余的,并且,我也在規(guī)定的時間內(nèi)完成了我自己所承擔(dān)的所有開發(fā)內(nèi)容,但是,誰知道一個星期后,這個項目還是沒有達到驗收標(biāo)準(zhǔn),原因就是我同事負(fù)責(zé)的一個功能運行得始終有問題。
簡單地說,同事負(fù)責(zé)開發(fā)的這個功能是需要同時向多個機械設(shè)備發(fā)送指令讓其按照規(guī)則運轉(zhuǎn),注意,是同步運轉(zhuǎn)!而問題也出在這里!
同事代碼出現(xiàn)問題的特征就是,他寫的代碼并不是百分百有效,有時候發(fā)送指令效果是正確的,即幾個機械設(shè)備在同時運轉(zhuǎn),但有時候就只有那么一兩個機械設(shè)備在運轉(zhuǎn)。
遇到這個問題,我首先想到的就是讓同事去調(diào)試,看看指令是否正確發(fā)到了每個機械設(shè)備上了。結(jié)果,這半個月,我同事當(dāng)著我的面調(diào)試了好幾次,發(fā)現(xiàn)指令發(fā)的都是對的!
開始,我還沒發(fā)現(xiàn)問題,后來當(dāng)問題解決了以后,我回想我每次看同事調(diào)試的時候的場景,我才意識到,我同事每次在調(diào)試的時候,設(shè)備都能正常運轉(zhuǎn)原因!
因為總是解決不掉問題,客戶那邊也擺爛了,隨我們搞,但是卻沒有給我們好臉色,這讓我有點被殃及池魚的感覺!
后來,直到有一天,我被客戶那邊一個PM給說了一頓后,情緒有點失控,所以,我就下定決心好好找一找我同事代碼中的茬!
因為同事需要操作的機械設(shè)備邏輯比較復(fù)雜,所以,我看著也有些迷迷糊糊的,所以一時半會兒也找不到問題出在哪!
最后,我決定使用排除法,把同事代碼中所有跟問題無關(guān)的代碼全部注釋掉,只留下關(guān)鍵代碼的方式去找問題,我不知道這方法有沒有用,但我還是決定死馬當(dāng)活馬醫(yī)!
誰知道,就是因為我的這一個操作,找到了導(dǎo)致代碼不能正確運行的原因!
因為代碼比較復(fù)雜,我在注釋同事寫的跟問題無關(guān)的代碼的時候,一邊問同事一邊注釋,結(jié)果當(dāng)我瞥到一個字段的時候,我竟然發(fā)現(xiàn)這個字段竟然是靜態(tài)的!
這個字段我其實一直很熟悉,它代表的是需要操作的設(shè)備的索引!我腦袋當(dāng)時就炸了,因為這個靜態(tài)字段所在的實體類是需要實例化的!我一直沒注意,以為它是類的實例字段。
首先,在一個需要實例化的實體類中放一個靜態(tài)字段本身就不太合適,除非這個靜態(tài)字段的值是個常量(勉強能解釋吧)。
但是,這個靜態(tài)字段表示的是設(shè)備的索引,在實例化后是要被賦值的,因此,靜態(tài)字段表示設(shè)備的索引,顯然是有問題的。
這么一想,我突然就豁然開朗了!
示例
示例
前面說了,同事代碼的問題點就是每次向設(shè)備發(fā)送指令的時候,就一兩個設(shè)備有響應(yīng),在調(diào)試代碼的時候,卻又是正常執(zhí)行的,即所有設(shè)備都能響應(yīng)。
問題恰恰就出在這個靜態(tài)字段上!
因為,向設(shè)備發(fā)送指令是使用線程異步發(fā)送的,而每次發(fā)送指令,都需要實例化一個發(fā)送指令的實體,并且給這個實體中的靜態(tài)字段即表示設(shè)備索引的字段賦值。
但是,因為是異步發(fā)送的,表示設(shè)備索引的那個字段又是靜態(tài)的,那么完全有可能在發(fā)送指令的時候,設(shè)備索引又被重新賦了值,從而導(dǎo)致指令沒有向正確的設(shè)備發(fā)送。
比如說,假設(shè)給設(shè)備索引的這個字段賦值為0,當(dāng)代碼還沒執(zhí)行到發(fā)送指令的代碼段時,其他線程又給設(shè)備索引賦值為了1,而當(dāng)兩個線程都走到了發(fā)送指令這塊代碼時,此時,設(shè)備索引這個字段的值也就只能是1了,造成的結(jié)果就是索引為0的設(shè)備沒有收到指令,而索引為1的設(shè)備,則收到了兩次指令!
而當(dāng)同一個設(shè)備收到相同指令時,新的指令會覆蓋舊的指令,因此,從感官上,不會有任何不正常的情況。
這個道理說通了,那么就可以解釋問題了,因為在極端情況下,是會出現(xiàn)只有一臺設(shè)備收到指令的情況,這種情況,代碼執(zhí)行得很快的話,概率是非常高的!
另外,也可以解釋為什么有時候只有一兩個設(shè)備收到了指令,因為只要設(shè)備索引這個靜態(tài)字段值在沒被下一個索引的值覆蓋前執(zhí)行了指令代碼,那么,相關(guān)設(shè)備就會收到指令信號!
至于調(diào)試的時候,為什么都能執(zhí)行正確呢?那就更簡單了,因為同事在代碼中下了斷點,阻礙了代碼的正常執(zhí)行,也就會導(dǎo)致設(shè)備索引這個字段是按照順序被賦值和發(fā)送指令的,因此就不會出問題!
結(jié)語
我嘆了一口氣,困擾了我們,準(zhǔn)確的說困擾了我同事半個月時間的問題,總算是找到了!我也是無語了,就問同事為什么會把設(shè)備索引這個字段寫成靜態(tài)的。
結(jié)果同事想了半天,也說不出個所以然來!最后我也不想說啥,只要項目能夠順利驗收就好!
在解決問題后,我總結(jié)了下,同事代碼出現(xiàn)問題有很多必然性,我到現(xiàn)在都搞不清楚為什么在一個實體類里面用靜態(tài)字段,還需要賦值!
最后,半個月啊!就這?
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.