Java------多线程_并发_非同步_三大经典案例 (七)

Java------多线程_并发_非同步_三大经典案例 (七)
线程同步要保证数据的安全性和正确性,以及性能。
代码上使用synon
高性能、高并发、高可用
并发:同一个对象多个线程同时操作。
并发的三个条件缺一不可,同一对象、多个线程、同时操作。
之前模拟抢票代码时,多个线程同时对一份资源进行操作,导致出现两种数据错误的表现:
1.抢到最后出现负数的情况。
2.抢的过程中出现多个线程使用同一票数的情况。多个线程从主存空间拷贝到各自工作内存中数据不一致。

/**
 * 线程不安全:数据出现负数、出现线程使用相同的数
 */
public class ThreadSyn {
    
    
    public static void main(String[] args) {
    
    
        UnSafe threadTest01 = new UnSafe();
        //多个代理,加入名称区分
        new Thread(threadTest01,"thread01").start();
        new Thread(threadTest01,"thread02").start();
        new Thread(threadTest01,"thread03").start();
    }

}

class UnSafe implements Runnable{
    
    
    private  int tickNums = 10;
    private  Boolean flag = true;
    @Override
    public void run(){
    
    
        while (flag){
    
    
            test();
        }
    }

    public void test(){
    
    
        if (tickNums<0){
    
    
            flag = false;
            return;
        }
        try {
    
    
            Thread.sleep(200);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"--->"+tickNums--);
    }

}

案例二:同时取钱的例子,即使在取钱时,加入判断,依然能取出去,造成账户余额为负数,两个人都能取到钱。

public class ThreadSyn02 {
    
    
    public static void main(String[] args) {
    
    
        Account account = new Account(100,"家庭基金");
        Draw draw = new Draw(account,70,"男人");
        Draw draw2 = new Draw(account,70,"女人");
        draw.start();
        draw2.start();
    }

}
//账户 Account
class Account{
    
    
    public int money;
    public String name;

    public Account(int money, String name) {
    
    
        this.money = money;
        this.name = name;
    }
}
class Draw extends Thread{
    
    
    Account account; //账户
    int drawingMoney;//取的钱
    int packetTotal;//口袋里的钱

    public Draw(Account account,int drawingMoney,String name){
    
    
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }


    @Override
    public void run() {
    
    
        //加上判断,当银行余额-取钱小于0时,不让取
        if (account.money-drawingMoney<0){
    
    
            return;
        }
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        account.money -= drawingMoney;
        packetTotal += drawingMoney;
        System.out.println(this.getName()+"---->账户余额"+account.money);
        System.out.println(this.getName()+"---->口袋余额"+packetTotal);
    }
}


案例三:容器一会出现线程不安全


/**
 * 容器不安全例子
 */
public class ThreadSyn03 {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> arrayList = new ArrayList<String>();
        for (int i = 0 ; i<100;i++){
    
    
            new Thread(()->{
               arrayList.add(Thread.currentThread().getName());
            }).start();
        }
        //最终打印结果,不到100
        System.out.println(arrayList.size());
    }
}

猜你喜欢

转载自blog.csdn.net/cz_chen_zhuo/article/details/121650163