编程细节|你的if缺少了一个else

2019-05-14  本文已影响0人  riki_tree

今天踩了一个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.变量使用前尽量判空。

上一篇下一篇

猜你喜欢

热点阅读