线程不安全三大问题_解决 同步方法及同步块

Posted liqiliang1437

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程不安全三大问题_解决 同步方法及同步块相关的知识,希望对你有一定的参考价值。

package com.qiliang.demo13_线程同步安全;
// 线程同步安全问题 , 卖票案例演示
public class UnSafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();

        new Thread(station,"小A").start();
        new Thread(station,"小B").start();
        new Thread(station,"黄牛党").start();
    }
}


class BuyTicket implements Runnable{
    // 定义票数
    private int ticketNums = 10;
    // 线程停止的标志位
    boolean flag = true;
    @Override
    public void run() {
        // 买票
        while (flag){
            buy();
        }
    }

    // synchronized 同步方法
    private synchronized void buy() {
        // 判断是否有票
        if(ticketNums<=0){
            flag = false;
            return;
        }

        // 模拟延时,放大问题的发生性
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}
// 线程不安全, 有负数
/*
黄牛党拿到10
小B拿到9
小A拿到8
黄牛党拿到7
小B拿到6
小A拿到5
黄牛党拿到4
小B拿到3
小A拿到2
黄牛党拿到1
小B拿到0
小A拿到-1
 */

``` java
package com.qiliang.demo13_线程同步安全;

// 线程同步安全问题,不安全的取钱案例
public class UnSafeBank {
    public static void main(String[] args) {
        Account account = new Account(1000, "结婚基金");

        Drawing xiaoli = new Drawing("小李", account, 50);
        Drawing xiaowang = new Drawing("小王", account, 100);

        xiaoli.start();
        xiaowang.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(String name, Account account, int drawingMoney) {
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;

    }

    // 取钱

    @Override
    public void run() {
       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);
           // Thread.currentThread().getName() = this.getName()
           System.out.println(this.getName()+"手里的钱:"+nowMoney);
       }

    }
}

``` java
package com.qiliang.demo13_线程同步安全;

import java.util.ArrayList;

// 线程不安全的集合
public class UnSafeList {
    public static void main(String[] args) throws InterruptedException {
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){
                list.add(Thread.currentThread().getName());
                }

            }).start();
        }
        Thread.sleep(3000);   // 9997  i=10000
        System.out.println(list.size()); // 918  i=1000
    }
}

以上是关于线程不安全三大问题_解决 同步方法及同步块的主要内容,如果未能解决你的问题,请参考以下文章

多线程:解决数据安全问题(同步代码块同步方法)

Java线程 — 线程同步及安全问题

线程的同步机制:同步代码块&同步方法

JAVA多线程_线程安全问题

Java多线程:线程同步详解

java中多线程安全性和同步的常用方法