php线程安全和非线程安全_线程安全和保证线程安全的两个方法

d8ced27a6bec84a42389d6c58009fa86.png

之前讲了什么是线程和多线程,接下来敲黑板:线程安全

什么是线程安全?线程安全就是确保程序在多线程运行的情况下,程序能够按照预期运行,不会存在二义性的结果。比如上一篇我们提到的火车票的售票问题,预期的情况下,我们需要确保同一张票只能被唯一的窗口售出一次。下面我们用代码说明:(我们这里调用Runnable实现多线程,不保证线程安全的情况)

Class1:实现一个Runnable接口

public 

Class2:例化Thread

public 

运行结果:

窗口1 售出 20号 票。

窗口2 售出 20号 票。

窗口1 售出 18号 票。

窗口2 售出 18号 票。

窗口2 售出 16号 票。

窗口1 售出 16号 票。

窗口2 售出 14号 票。

窗口1 售出 13号 票。

窗口2 售出 12号 票。

窗口1 售出 11号 票。

窗口2 售出 10号 票。

窗口1 售出 9号 票。

窗口2 售出 8号 票。

窗口1 售出 7号 票。

窗口2 售出 6号 票。

窗口1 售出 5号 票。

窗口2 售出 4号 票。

窗口1 售出 3号 票。

窗口2 售出 2号 票。

窗口1 售出 1号 票。

从上面结果来看,其中20号票被窗口1和窗口2同时出售两次,而19号票则没有卖出,这显然是售票系统出现了问题。(ps:每次运行的情况可能不会相同,可以试着多运行几次,对比结果)

下面我们看一下保证线程安全的两种方法:

第一种:synchronized关键字,将操作共享数据的语句加入synchronized关键字,在某一时段只会让一个线程执行完,在执行过程中,其他线程不能进来执行。如下代码,只需将class1增加如下标记部分:

public 

运行结果:

窗口1 售出 20号 票。

窗口1 售出 19号 票。

窗口1 售出 18号 票。

窗口2 售出 17号 票。

窗口2 售出 16号 票。

窗口2 售出 15号 票。

窗口2 售出 14号 票。

窗口2 售出 13号 票。

窗口1 售出 12号 票。

窗口1 售出 11号 票。

窗口1 售出 10号 票。

窗口2 售出 9号 票。

窗口1 售出 8号 票。

窗口2 售出 7号 票。

窗口2 售出 6号 票。

窗口1 售出 5号 票。

窗口2 售出 4号 票。

窗口2 售出 3号 票。

窗口1 售出 2号 票。

窗口2 售出 1号 票。

从上面结果看,这样子就能达到预期所需要的售票效果,并且运行多次,结果也都是预期内的。

第二种:使用Lock锁,Lock使用起来比较灵活,但需要手动释放和开启。在并发量比较高的情况下,synchronized会让性能下降,此时使用Lock是个不错的方案。如下代码,只需将class1增加如下标记部分:

public 

运行结果:

窗口1 售出 20号 票。

窗口1 售出 19号 票。

窗口1 售出 18号 票。

窗口1 售出 17号 票。

窗口1 售出 16号 票。

窗口1 售出 15号 票。

窗口1 售出 14号 票。

窗口1 售出 13号 票。

窗口1 售出 12号 票。

窗口1 售出 11号 票。

窗口1 售出 10号 票。

窗口1 售出 9号 票。

窗口2 售出 8号 票。

窗口1 售出 7号 票。

窗口2 售出 6号 票。

窗口1 售出 5号 票。

窗口1 售出 4号 票。

窗口2 售出 3号 票。

窗口2 售出 2号 票。

窗口1 售出 1号 票。

运行结果和使用synchronized一致,不会出现一票多卖等情况。另外需要补充的是Lock需要手动去获取和释放锁,所以必须放在try--catch语句块中,将lock.unlock()放在finally{}中,确保之后的线程也能获取。Lock还有trylock也可以用来获取锁,并且有返回值,若果获取成功,会返回true,若获取失败,(锁被其他线程占用)则返回false,但是若获取失败不会像lock()方法一样一直等。但是有一个带参的trylock(long time,TimeUnit unit),意思是:获取不到锁,就等待所给定的时间,如果还是获取不带,就返回false。TimeUnit表示给定单元粒度的时间段。当然Lock还有其他的方法,有兴趣的可以继续了解一下。


联系我:

c5ab0e0b633301b5b23e20e126a8535a.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值