今天踩了一个if-else的坑。
事故现场:
程序结构如图:
struct.png
采用伪代码表述:
/**
* 服务器传过来值:1或者2
* 客户端根据传值修改变量:水果状态1或者2
*
* 函数()
* {
* 水果=null;
*
* if(水果状态==1)
* {
* 水果=new 苹果();
* }
* elseif(水果状态==2)
* {
* 水果=new 猕猴桃();
* }
*
* 水果.打印();
*}
*/
程序一直好好地运行着。直到某一天,某同学触发了服务器某个机关,服务器不断的给客户端发送这条消息,然后客户端就崩掉了。
事故还原:
用线程不断修改key来模拟服务器传递过来的消息,主线程添加一个临时变量,来打印东西。代码如下:
public static int Key = 1; //根据key值打印不同的数据
//线程1不断修改key值为1
public static void ChangeKey()
{
while (true)
{
Key = 1;
}
}
//线程1不断修改key值为2
public static void ChangeKey2()
{
while (true)
{
Key = 2;
}
}
//根据key值打印不同的字符串
public static void PrintStr()
{
string str = "空值";
if (Key==1)
{
str = "现在key是1";
}
else if (Key == 2)
{
str = "现在key是2";
}
Console.WriteLine(str);
}
//主函数
static void Main(string[] args)
{
//开启两个线程
Thread thread1 = new Thread(new ThreadStart(ChangeKey));
Thread thread2 = new Thread(new ThreadStart(ChangeKey2));
thread1.Start();
thread2.Start();
Thread.Sleep(50);
//主线程执行50次打印函数
int i = 0;
while (i<=50)
{
i++;
PrintStr();
}
}
猜测一下打印的东西都是什么?
if_else.gif
Key值只有1,2两种情况啊,判断语句要么执行第一句,要么执行第二句,怎么可能出现空值呢。显然if-else出了问题。
事故分析:
其实上述例子跟文章开头的事故还是有一定的差别的。但是出问题的原因是一样的。先说例子,多线程之间的资源共享,或者说资源抢占导致的。具体看图片流程:
first.png
接着下一步:
second.png
问题出现了。再说开局的例子,根据服务器传送过来的状态执行函数,本身就相当于多线程。因此在if-else的空隙,导致“水果=null”,接着再用“水果.打印()”就发生了崩溃的情况。
小结:
当然解决办法有很多种,要根据自身项目需求来定。这里只是提几个编程细节:
1.变量初始化即给初值,尽量避免使用null;
2.if和else配对使用;
3.变量使用前尽量判空。
网友评论