Java------多线程_并发_同步_性能分析与影院例子(九)

Java------多线程_并发_同步_性能分析与影院例子(九)
同步块可以更小的锁定资源。
将之前的抢票案例修改一下
由同步方法,改为同步块格式。
该案例:线程由两个因素决定,分别是票数、和falg标识,但synchronized同步块只能锁一个内容。
因此需要包装。
案例一:

/**
 * 线程安全:保证数据的安全性,同时效率尽可能高
 * 第一个例子:抢票
 * synchronized:同步块与同步方法,效率对比
 */
public class ThreadSyn04 {
    
    
    public static void main(String[] args) {
    
    
        UnSafe04 threadTest01 = new UnSafe04();
        //多个代理,加入名称区分
        new Thread(threadTest01,"thread01").start();
        new Thread(threadTest01,"thread02").start();
        new Thread(threadTest01,"thread03").start();
    }

}

class UnSafe04 implements Runnable{
    
    
    private  int tickNums = 10;
    private  Boolean flag = true;
    @Override
    public void run(){
    
    
        while (flag){
    
    
            test();
        }
    }
    //同步块,
    public  void test(){
    
    
        synchronized(this){
    
    
            if (tickNums<0){
    
    
                flag = false;
                return;
            }
            try {
    
    
                Thread.sleep(200);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--->"+tickNums--);
        }

    }

}

但是这个synchronized其实还是将方法内部全部锁住,和synchronized方法没有什么区别。而
改成这样,只锁flag又锁不住,还会造成线程不安全的情况。
锁的大了,造成性能下降,锁的区域小了,线程又不安全。

synchronized(this){
    
    
            if (tickNums<0){
    
    
                flag = false;
                return;
            }
          }

粒度更小,保证数据的完整性

    //同步块,
    public  void test(){
    
    
        //尽可能锁定合理的范围(不是指代码,而是指数据的完整性)
        //double checking
        if (tickNums<=0){
    
    
            flag = false;  //考虑的是没有票的情况,不用判断
            return;
        }
        synchronized(this){
    
    
            if (tickNums<=0){
    
    
                flag = false; //考虑最后一张票的情况,粒度更小
                return;
            }
            try {
    
    
                Thread.sleep(200);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--->"+tickNums--);
        }
    }

案例二影院订票:

/**
 * 快乐影院例子
 */
public class ThreadSyn05 {
    
    
    public static void main(String[] args) {
    
    
        Cinema cinema = new Cinema(100,"我的影院");
        Customer customer = new Customer(cinema,80);
        Customer customer2 = new Customer(cinema,80);
        new Thread(customer).start();
        new Thread(customer2).start();

    }

}

//影院 Cinema
class Cinema{
    
    
    public int avaliabe;  //可用位置
    public String name;   //名称

    public Cinema(int avaliabe, String name) {
    
    
        this.avaliabe = avaliabe;
        this.name = name;
    }
    //购票
    public boolean bookTickets(int seats){
    
    
        System.out.println("可用位置为:"+avaliabe);
        if (seats > avaliabe){
    
    
            return false;
        }else {
    
    
            avaliabe -= seats;
            return true;
        }
    }
}
//顾客
class Customer implements Runnable{
    
    
    Cinema cinema; //账户
    int seats;//位置


    public Customer(Cinema cinema,int seats){
    
    
        this.cinema = cinema;
        this.seats = seats;
    }


    @Override
    public void run() {
    
    
        boolean flag;
        synchronized (cinema){
    
    
            flag = cinema.bookTickets(seats);
            if (flag){
    
    
                System.out.println("出票成功:"+Thread.currentThread().getName()+"---位置为:"+seats);
            }else {
    
    
                System.out.println("出票失败"+ Thread.currentThread().getName()+"---位置不够");
            }
        }

    }
}


此时还不满足,选位子的情况,因此需要再完善。
如下:

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

/**
 * 快乐影院例子
 */
public class ThreadSyn051 {
    
    
    public static void main(String[] args) {
    
    
        List<Integer> cinemaList = new ArrayList<>();
        cinemaList.add(1);
        cinemaList.add(2);
        cinemaList.add(3);
        cinemaList.add(5);
        cinemaList.add(8);
        cinemaList.add(9);
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        List<Integer> list2 = new ArrayList<>();
        list2.add(7);
        list2.add(9);

        Cinema1 cinema = new Cinema1(cinemaList,"我的影院");
        Customer1 customer = new Customer1(cinema,list1);
        Customer1 customer2 = new Customer1(cinema,list2);
        new Thread(customer).start();
        new Thread(customer2).start();

    }

}
//影院 Cinema
class Cinema1{
    
    
    public List<Integer> avaliabe;  //可用位置
    public String name;   //名称

    public Cinema1(List<Integer> avaliabe, String name) {
    
    
        this.avaliabe = avaliabe;
        this.name = name;
    }
    //购票
    public boolean bookTickets(List<Integer> seats){
    
    
        System.out.println("可用位置为:"+avaliabe);
        if (seats.size() > avaliabe.size()){
    
    
            return false;
        }
        List<Integer> copy = new ArrayList<>();
        //赋值
        copy.addAll(avaliabe);
        //相减
        copy.removeAll(seats);
        //判断座位是否足够
        if (avaliabe.size() - copy.size() != seats.size()){
    
    
            return false;
        }
        //赋值
        avaliabe = copy;
        return true;
    }
}
//顾客
class Customer1 implements Runnable{
    
    
    Cinema1 cinema; //账户
    List<Integer> seats;//位置


    public Customer1(Cinema1 cinema,List<Integer> seats){
    
    
        this.cinema = cinema;
        this.seats = seats;
    }
    @Override
    public void run() {
    
    
        boolean flag;
        synchronized (cinema){
    
    
            flag = cinema.bookTickets(seats);
            if (flag){
    
    
                System.out.println("出票成功:"+Thread.currentThread().getName()+"---位置为:"+seats);
            }else {
    
    
                System.out.println("出票失败"+ Thread.currentThread().getName()+"---位置不够");
            }
        }

    }
}


猜你喜欢

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