package java11;
class Ticket /*implements Runnable*/extends Thread
{
private static int tick = 100;
@Override
public void run() {
while(true)
{
// 卖一张
if(tick>0)
{
// 下面是打印剩余票数 (第一种写法)
System.out.println(Thread.currentThread().getName()+"....sale : "+ ( (tick--) -1 ) );
}
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
t1.start();
t2.start();
}
}
// 基于静态变量的共享,这个是前提,也是没有争议的理论. 那么有下面现象出现.
// 请注意,打印剩余票数的那行. 注意那个tick--.我们期待的结果打印一百次. 从99~0(结果不一定有序) 之间不同的值分别出现一次;
// 然而,事实上,你多运行几次, 会发现, 打印结果偶尔会出现重复的值.99~0之间的值某个可能出现不止一次!!
// 下面是正确写法
// 那么把打印剩余票数的那行,改写成
// System.out.println(Thread.currentThread().getName()+"....sale : "+ (--tick)); (第二种写法)
// 结果运行测试很多次, 打印一百次,99~0之间的值每个出现一次,不会有重复的值出现.
// 下面是原因分析:
//第一种写法,先输出 ,再执行票数减1; 例如: 在 其中一个线程得到票数值100,之后输出了剩余票数99, 注意,这个线程还未完成后续的 100减1操作时, 另一个线程得到的票数值是100,并且也会输出剩余票数99, 之后再去完成100-1操作. 这就导致了 可能会重复打印99; 当然 ,任何一个值都可能重复打印出现两次.
// 第二种写法. 例如, 在其中一个线程得到票数值100, 先完成100减1操作, 再打印剩余99; 即使这个线程的后续输出剩余99还未执行前, 另一个线程得到了票数值, 此时的票数值已经是99了,他不可能打印出剩余99了,只会打印出剩余98 !!
// 就是这么多了! 自己搞了很久. 发现网上的很多例子,还有视频,都会写出这个错误写法. 当然,尽管这两种写法,打印的结果不同,但是静态变量确实是共享的. 这是线程的执行导致.
// 有不对之处望同行指出,谢谢阅读.