文章目录[隐藏]
1. 你知道线程安全问题吗?
线程安全问题:一般指在多线程模式下,多个线程对同一个共享数据进行操作时,第一个线程还没来得及更新共享数据,从而导致另外一个线程没得到最新的数据,并更新数据,从而产生线程安全问题。比较常见的场景有买票。
我举个例子吧:
需求:比如买周杰伦演唱会的门票,此时有三个窗口同时卖总共100张票。窗口就是线程对象,而100张票的资源,此时就相当于多个线程去抢占cpu的资源去抢对票的使用权。
嘿嘿,这是在大学时期和MyGirl去看滴,现在想去看也没办法了。话不多说,我们还是来看看代码吧:
public class SellTicketDemo { public static void main(String[] args) { // 创建线程任务对象 Ticket ticket = new Ticket(); //创建三个窗口对象 Thread thread = new Thread(ticket, "窗口1"); Thread thread2 = new Thread(ticket, "窗口2"); Thread thread3 = new Thread(ticket, "窗口3"); //同时卖票 thread.start(); thread2.start(); thread3.start(); } } // 创建Ticket实现Runnale class Ticket implements Runnable { private int<strong style="color:transparent">本文来源gao@daima#com搞(%代@#码网@</strong> ticket = 100; // 100张周杰伦演唱会门票 // 执行买票的逻辑 @Override public void run() { // 注意每个窗口都有卖票的权利 while (true) { if (ticket > 0) { // 有票 可以卖 // 出票: 因为进来买票,总有出票,总会慢慢没票的吧 try { // 这里采用sleep稍微等待下,模拟一下出票时间 。 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 获取当前线程对象的名字 System.out.println(Thread.currentThread().getName() + "正在卖:" + ticket--); } } } }
这里讲下: 我们创建了Ticket实现Runnable接口,并重写里面的run方法实现买票的功能,并定义了一个共享的变量。并在main方法中创建了三个线程去实现三个窗口买票的功能。最后我们来看看结果吧:
在你多运行几次,可以看到这样的现象:
- 卖出了不存在的票,比如0票与-1票,是不存在滴。而且这种情况根本不允许发生呀,谁会卖0张甚至-1张票呢。
- 出现多卖相同的票数,比如8和1这张票被卖了三回。那这就很过分了呦,一张票还可以卖三个人哈哈。
这些问题的发生就代表我们刚才是线程不安全的了。那线程安全问题具体是什么呢?我们可以总结得到:
是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。