毕向东老师实现Runnable接口的卖票线程,程序运行会出现不同线程卖重复票的有关问题,这是什么原因

毕向东老师实现Runnable接口的卖票线程,程序运行会出现不同线程卖重复票的问题,这是什么原因?
public class demo implements Runnable {
private int n=10;;

@Override
public void run() {
// TODO Auto-generated method stub
sale();
}
public  void sale()
{
while(true)
{
if(n>0)
System.out.println(Thread.currentThread().getName()+"..."+n--);
else
break;
}
}
}


public static void main(String[] args) throws FileNotFoundExceptionIOExceptionClassNotFoundException {
// TODO Auto-generated method stub

demo d=new demo();
Thread d1=new Thread(d);
Thread d2=new Thread(d);
Thread d3=new Thread(d);
Thread d4=new Thread(d);

d1.start();
d2.start();
d3.start();
d4.start();
}
程序运行结果出现两个10:
Thread-0...10
Thread-0...7
Thread-0...6
Thread-0...5
Thread-0...4
Thread-0...3
Thread-0...2
Thread-2...8
Thread-3...9
Thread-1...10
Thread-0...1
------解决思路----------------------
售票方法 sale 方法没有加锁,每个线程可能同时拿到剩余票数,这样同一张票就会被卖多次
加锁就好了 

public synchronized void sale() {
while (true) {
if (n > 0)
System.out.println(Thread.currentThread().getName() + "..."
+ n--);
else
break;
}
}