三大不安全案例

一、买票(加了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());
    }
}

运行结果

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/419725f5-a230-4137-90ff-86e44b6f6fea/Snipaste_2021-04-26_16-49-14.png

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b070b780-c9ad-4adc-8be1-b37a9d2ab138/Snipaste_2021-04-26_17-21-13.png

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f3c5ead5-8b7f-4816-ab17-ba0dbac511f1/Snipaste_2021-04-26_17-42-59.png


synchronized 锁

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/952300b7-5353-42cb-9a77-b57c00587bab/BC6C9D24-E123-49DD-919C-A1A3ACF1E1A3.jpeg

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/59053f98-8f8b-47b6-8e42-868ddece1c3f/22ECE78F-A1B6-4C0A-8139-298A2CCA27C1.jpeg

/