三大不安全案例

一、买票(加了synchronized )

package top.ltyzqhh.thread.study;

//不安全的买票
//线程不安全有负数
public class syn {

    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 ticketNums=10;
    boolean flag =true;//外部停止方式
    @Override
    public void run() {
        //买票
        while(flag){
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //synchronized 同步方法 锁的是this
    private synchronized void buy() throws InterruptedException {
        if (ticketNums<=0)
        {
            flag=false;
            return;
        }
        //模拟延时
        Thread.sleep(100);
        //买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}

二、不安全的取钱

//不安全的取钱
public class UnsafeBank {
    public static void main(String[] args) {
        //账户
        Account account=new Account(100,"结婚基金");

        Drawing you = new Drawing(account,50,"你");
        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;
    }

    //取钱
    // synchronized 默认锁的是this.
    @Override
    public  void run() {
        //synchronized 同步块 锁的对象是变化的两,需要增删改的对象
        synchronized (account){
            //判读有没有钱
            if(account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够了");
                return;
            }

            //sleep 可以放大问题的发生性
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //卡内余额=余额-你取的钱
            account.money=account.money-drawingMoney;
            //你手里的钱
            nowMoney=nowMoney+drawingMoney;
            System.out.println(account.name+"余额为"+account.money);
            //Thread.currentThread().getName()=this.getName();
            System.out.println(this.getName()+"手里的钱:"+nowMoney);
        }

    }
}

三、线程不安全的集合

package top.ltyzqhh.thread.study;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();

        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){
                    list.add(Thread.currentThread().getName());
            }

            }).start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

运行结果


synchronized 锁

/