今天踩了一個(gè)if-else的坑。
事故現(xiàn)場(chǎng):
程序結(jié)構(gòu)如圖:

struct.png
采用偽代碼表述:
/**
* 服務(wù)器傳過(guò)來(lái)值:1或者2
* 客戶端根據(jù)傳值修改變量:水果狀態(tài)1或者2
*
* 函數(shù)()
* {
* 水果=null;
*
* if(水果狀態(tài)==1)
* {
* 水果=new 蘋果();
* }
* elseif(水果狀態(tài)==2)
* {
* 水果=new 獼猴桃();
* }
*
* 水果.打印();
*}
*/
程序一直好好地運(yùn)行著。直到某一天,某同學(xué)觸發(fā)了服務(wù)器某個(gè)機(jī)關(guān),服務(wù)器不斷的給客戶端發(fā)送這條消息,然后客戶端就崩掉了。
事故還原:
用線程不斷修改key來(lái)模擬服務(wù)器傳遞過(guò)來(lái)的消息,主線程添加一個(gè)臨時(shí)變量,來(lái)打印東西。代碼如下:
public static int Key = 1; //根據(jù)key值打印不同的數(shù)據(jù)
//線程1不斷修改key值為1
public static void ChangeKey()
{
while (true)
{
Key = 1;
}
}
//線程1不斷修改key值為2
public static void ChangeKey2()
{
while (true)
{
Key = 2;
}
}
//根據(jù)key值打印不同的字符串
public static void PrintStr()
{
string str = "空值";
if (Key==1)
{
str = "現(xiàn)在key是1";
}
else if (Key == 2)
{
str = "現(xiàn)在key是2";
}
Console.WriteLine(str);
}
//主函數(shù)
static void Main(string[] args)
{
//開啟兩個(gè)線程
Thread thread1 = new Thread(new ThreadStart(ChangeKey));
Thread thread2 = new Thread(new ThreadStart(ChangeKey2));
thread1.Start();
thread2.Start();
Thread.Sleep(50);
//主線程執(zhí)行50次打印函數(shù)
int i = 0;
while (i<=50)
{
i++;
PrintStr();
}
}
猜測(cè)一下打印的東西都是什么?

if_else.gif
Key值只有1,2兩種情況啊,判斷語(yǔ)句要么執(zhí)行第一句,要么執(zhí)行第二句,怎么可能出現(xiàn)空值呢。顯然if-else出了問(wèn)題。
事故分析:
其實(shí)上述例子跟文章開頭的事故還是有一定的差別的。但是出問(wèn)題的原因是一樣的。先說(shuō)例子,多線程之間的資源共享,或者說(shuō)資源搶占導(dǎo)致的。具體看圖片流程:

first.png
接著下一步:

second.png
問(wèn)題出現(xiàn)了。再說(shuō)開局的例子,根據(jù)服務(wù)器傳送過(guò)來(lái)的狀態(tài)執(zhí)行函數(shù),本身就相當(dāng)于多線程。因此在if-else的空隙,導(dǎo)致“水果=null”,接著再用“水果.打印()”就發(fā)生了崩潰的情況。
小結(jié):
當(dāng)然解決辦法有很多種,要根據(jù)自身項(xiàng)目需求來(lái)定。這里只是提幾個(gè)編程細(xì)節(jié):
1.變量初始化即給初值,盡量避免使用null;
2.if和else配對(duì)使用;
3.變量使用前盡量判空。