举两个例子,不安全的取票系统和不安全的银行取钱系统
出现这种情况的原因是有可能几条线程同时操作一个对象的时候冲突了,导致几条线程取到的是同一张票
//这是一个不安全的买票系统
//出现了负数和重复的数,这不是我们想得到的情况
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{
//总共10张票
private int ticketNum=10;
//设置一个标记位
private boolean flag=true;
@Override
public void run() {
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void buy() throws InterruptedException {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"抢到了第"+ticketNum--+"张票");
if(ticketNum<=0){
flag=false;
}
return;
}
}
/*
穷学生抢到了第9张票
农民工大叔抢到了第10张票
可恶的黄牛党抢到了第8张票
可恶的黄牛党抢到了第7张票
穷学生抢到了第5张票
农民工大叔抢到了第6张票
穷学生抢到了第4张票
农民工大叔抢到了第3张票
可恶的黄牛党抢到了第2张票
可恶的黄牛党抢到了第1张票
农民工大叔抢到了第-1张票
穷学生抢到了第0张票
*/
public class Bank {
public static void main(String[] args) {
DrawingMoney drawingMoney = new DrawingMoney(new Account(50,"结婚基金"),50,0);
Thread you = new Thread(drawingMoney,"你");
Thread her = new Thread(drawingMoney,"你女朋友");
you.start();
her.start();
}
}
//账户
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//模拟银行取钱
class DrawingMoney implements Runnable {
//账户里有多少钱
Account account;
//取了多少钱
int drawmoney;
//手里有多少钱
int havemoney;
//取钱
public DrawingMoney(Account account, int drawmoney, int havemoney) {
this.account = account;
this.drawmoney = drawmoney;
this.havemoney = havemoney;
}
@Override
public void run() {
if(account.money<drawmoney){
System.out.println("账户里钱不够了");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
havemoney=havemoney+drawmoney;
System.out.println(Thread.currentThread().getName()+"取了"+drawmoney);
account.money= account.money-drawmoney;
System.out.println(account.name+"余额为"+account.money);
}
}
如何解决线程不安全的问题
很简单,只需要在方法前面加一个修饰词synchronized
这是一个队列和锁的机制
synchronized{ } 块锁的是需要增删改查的变量