多线程并发与同步及不安全因素
错误示例:
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
//将这个对象通过三个线程来买票
new Thread(buyTicket,"小王").start(); //小王线程
new Thread(buyTicket,"小张").start(); //小张线程
new Thread(buyTicket,"小李").start(); //小李线程
}
}
class BuyTicket implements Runnable{
//票的数量
private int num = 10;
boolean flag = true;//外部停止方式
@Override
public void run() {
while (flag) {
buy();
}
}
private void buy(){
//哦安短是否有票
if (num<=0){
flag = false;
return;
}
System.out.println(Thread.currentThread().getName()+"拿到"+num--);
}
}
输出列表:(不唯一,由线程创建时的细节所决定)
小王拿到10
小王拿到9
小王拿到8
小张拿到10
小王拿到7
小李拿到5
小张拿到6
小张拿到2
小李拿到3
小王拿到4
小张拿到1
那么问题来了,为什么同一个对象,三个线程来操作,会出现两个人拿到同一张票的情况?
原因:线程运行时有单独的存储空间,互不干扰,比如第0时刻,对象的num值为0,此时,小王线程和小张线程同时读取了这个0的值到自己的存储空间,就会造成买到同一张票的情况。
解决方法:
private void buy()修改为:
private synchronized void buy()
原理:synchronized将this指针锁住,即多个线程在执行同一个对象时候,当一个线程在执行synchronized修饰过的代码时,会将对象锁住从而阻止其他进程的执行,其他的进程到了对应位置就会阻塞。