最近写了一个高并发的代码
public String getTicketForRedis(){Long ticket = redisTemplate.opsForValue().decrement("ticket");ticket = ticket--;if(ticket>=0){ticketService.updateTicketNum();System.out.println("票号为:"+ ticket);return "票号为:"+ ticket;}else{return "光了";}}
一直以为出现线程不安全的地方是 ticket = ticket–;if(ticket>=0) 就是这个ticket可能是同一个数,为什么是同一个数那 因为当线程切换时,ticket = tocket-- 不是原子性的。咋一看,是有道理 其实不然 这个方法内的操作,根据jvm内存模型,方法内的变量在方法栈中 每个线程都有一个方法栈,切线程安全,互不影响。所以 方法内的所有操作,都是线程安全的。但这里在高并发下确实会出现票的超卖。问题在于获取ticket时 由于mysql的原因,每个线程很可能取到相同的数,所以减票数会出现超过100张票数。
总结:
引起 线程问题的原因: 1 成员变量 2 数据库引入方法中的局部变量