线程不安全实例
买票问题
public class UnSafeBuyTicket {
public static void main(String[] args) {
BuyTicket station =new BuyTicket();
new Thread(station,"我").start();
new Thread(station,"你们").start();
new Thread(station,"黄牛").start();
}
}
class BuyTicket implements Runnable{
//票
private int ticketNums=10;
boolean flag=true;//外部停止方式
@Override
public void run(){
//买票
while(flag){
try{
buy();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public void buy() throws InterruptedException {
//判断是否有票
if(ticketNums<=0){
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--);
}
}
//线程不安全,有负数
//输出的是
//黄牛拿到了10
//我拿到了8
//你们拿到了9
//黄牛拿到了7
//你们拿到了6
//我拿到了5
//黄牛拿到了4
//你们拿到了3
//我拿到了2
//黄牛拿到了1
//你们拿到了0
//我拿到了-1
解决办法
// 同步方法,锁的是this
public synchronized void buy() throws InterruptedException {
//判断是否有票
if(ticketNums<=0){
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--);
}
// 或者
private final ReentrantLock lock=new ReentrantLock();
@Override
public void run(){
//买票
while(flag){
try{
lock.lock();
try{
buy();
}catch(InterruptedException e){
e.printStackTrace();
}
}finally{
lock.unlock();
}
}
}
取钱问题
public class UnsafeBank {
public static void main(String[] args) {
Account account=new Account(100,"结婚基金");
Drawing you=new Drawing(account,50,"you");
Drawing girlfriend=new Drawing(account,100,"girlfriend");
you.start();
girlfriend.start();
}
}
class Account{
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
};
class Drawing extends Thread{
Account account;
// 取出来多少钱
int drawingMoney;
// 手里的钱
int nowMoney;
public Drawing(Account account,int drawingMoney,String name){
super(name);
this.account=account;
this.drawingMoney=drawingMoney;
}
//取钱
@Override
public void run(){
//判断有没有钱
if(account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够了,取不了");
return;
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
account.money=account.money-drawingMoney;
nowMoney=nowMoney+drawingMoney;
System.out.println(account.name+"余额为"+account.money);
System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);
}
}
解决办法
//取钱
@Override
public void run(){//如果在这一行加synchronized,那么锁的是银行,没啥用
synchronized (account){//锁的是账户
//判断有没有钱
if(account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够了,取不了");
return;
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
account.money=account.money-drawingMoney;
nowMoney=nowMoney+drawingMoney;
System.out.println(account.name+"余额为"+account.money);
System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);
}
集合问题
import java.util.ArrayList;
import java.util.List;
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}
// 输出的结果达不到10000
解决办法
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();