Java-初步认识-第十三章-多线程(线程安全问题的现象)
一. 引言
接着看,把售票的问题给说完,这里涉及到一个小问题。
在我们进行线程任务封装,并进行线程对象创建的时候,我们发现确实通过四个线程能够将一百张票卖完。但是卖票的时候,会不会出现一些小问题呢?分析整个程序给大家展示一下。
现在有四个线程,都到了run方法中来运行。大家都知道,每个线程所属的栈区当中都有自己的run方法,比如它们同时在操作堆内存中的变量,叫做num。
假设这个num已经减到了1,这是个前提。
在num=1的情况下,四个线程Thread-0,Thread-1,Thread-2,Thread-4,都同时进入循环。在Thread-0线程举着num=1,判断完if(num>0)后,cpu切出去执行其他线程的if判断语句了。也就是说保有执行资格,没有执行权。在四个线程判别完之后,cpu回过来执行了Thread-0线程,输出了DOS信息,Thread-0,1,此时num=0了。
同时卧倒的线程还有三个,它们都不用再进行判断了。线程1在执行的时候,输出的是Thread-1,0。当线程输出0的时候,就出事儿了。哪有0号票的,同样的线程3输出的是Thread-3,-1。
这个程序分析完,我们发现存在安全隐患。这就是我们在写多线程程序的时候,必须要注意的一件事。线程的安全问题。
二.
线程的完全问题,多线程是随机的,它就会引发一些安全隐患。这些安全隐患对我们来说是很严重的。
有人说,我们上面的程序在编译运行的时候,没有问题。但那都是理想状态,刚才我们的分析的状态是有可能出现的。
现在将这种情况实现以下,将线程在卧倒的时候稍微停一下,也就是睡一下。有人说,睡不是释放资格吗?不怕,睡的时间特别短就没事。它具备的资格,没有执行权和睡的时间短是一回事。因为都在这段时间内,不运行。
线程怎么睡,自己知道,到Thread类中寻找方法。
下面的sleep方法,是纳秒。由于sleep方法是静态的,所以要类名调用。
点进sleep方法中,发现还有异常的存在。这个异常是中断异常,后面会重点给大家介绍。
我们现在调用了一个抛出异常的方法,那应该怎么办?要么声明throws,要么try-catch处理。如果catch不了,就声明出来。
在if代码块的Thread.sleep(10);语句中,遇到异常了,那么我们就要选择抛出,
但是在这里是抛不出去,你声明不了,是因为这run覆盖的是接口中的方法,接口没有声明过异常,所以覆盖时,你也不能声明异常。
你只能try-catch,确切地说,你只能catch,而不能声明。这就是只能catch,不能声明的情况。
咱这异常目前处理不了,还没开始学习怎么处理这个异常。
这里就没进行处理,但是真实的catch里面一定要有处理,而且是针对性的处理。
这么写,给大家看一下是否有错号票发生么?
这次结果中只出了-1,没有出-2,,只是想说这么个事儿,自己运行的时候,没有看到-1,-2,因为到这种情况,当变成0的时候,其他线程才进来,一判断不满足就不运行了。
现在的结果将之前谈论的安全问题发生了,像这种问题,我们不做下面截图中那句话,代码运行很多次都没有问题,但是只要出现一次就很严重。它不是时时刻刻都出现的,但是不代表它没有安全问题。
因此,我们在写多线程程序的时候,要考虑线程的安全问题。我们要考虑的是造成安全问题的原因是什么?