线程同步(重点难点)

1.什么叫线程同步?

统一进行的多个线程共享同一块存储空间,在带来方便的同事,也带来了访问冲突文图,为了保证数据在方法中别访问时的正确性,在访问时加入锁机制,synchronized ,当某一个线程获取得对象的排它锁,独占资源,其他下次讷航必须等待,执行完后,释放锁即可。 存在以下问题:

1.一个线程持有锁会导致其他所有需要次所的线程挂起;

2.再多贤臣竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题

3.如果一个优先高的线程等待一个优先级低的线程释放锁,对导致倒置,引起性能问题。

(多个线程同时操作一个程序,导致线程不安全,所以提出来一个线程同步的概念,实际就是一个等待机制。比如多人买票,食堂吃饭排队,同一张一行卡同一时间用不同的方式取钱等等。)

2.对象的等待池

由于多个需要同时访问的线程去访问同一个方法时,会出现线程不安全的问题,所以会让线程入到对象的等待池。

3.队列和锁

每个对象都拥有一把锁,队列加锁才能保证线程的一个安全性 synchronized ,让多个线程同时进入到对象的等待池,对他们进行排队,一个一个来,根据顺序进行线程开启,当一个线程执行之前,获取一个线程锁,执行完之后,释放锁,进行下一个执行。从而保证了线程的安全。

4.三大不安全案例 (购买车票、银行取钱、ArrayList线程不安全)

package com.thread.security;

/**
 * @description:  线程安全测试 ------------- 买票
 * @author:wt
 * @createTime:2021/9/16 11:13
 * @version:1.0
 */
public class ThreadSecurity1 {
    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 ticketNum = 10 ;
    boolean flag = true;
    @Override
    public void run() {
        while (flag){
            buy();
        }
    }

    private void buy (){
        if (ticketNum <= 0){
            flag = false;
            return;
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"购买到第* "+ ticketNum-- + " *张票!");
    }
}
package com.thread.security;

/**
 * @description:   银行取钱场景
 * @author:wt
 * @createTime:2021/9/18 14:57
 * @version:1.0
 */
public class ThreadSecurity2 {
    public static void main(String[] args) {
        Account account = new Account(100,"邮政卡");
        // 取钱
        Drawing zs = new Drawing(account,50 , "张三");
        Drawing ls = new Drawing(account,80 , "李四");
        zs.start();
        ls.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.money );
        System.out.println(this.getName()+"手里的钱:" + nowMoney );


    }
}
package com.thread.security;

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

/**
 * @description: 线程不安全
 * @author:wt
 * @createTime:2021/11/11 17:43
 * @version:1.0
 */
public class UnSafeLife {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        Thread.sleep(3000);
        System.out.println(list.size());
    }
}

猜你喜欢

转载自blog.csdn.net/wt5264/article/details/120227331
今日推荐