(二)线程同步_3---在类中使用相互独立的属性同步

在类中使用相互独立的属性同步

当使用synchronized关键字去同步一个代码块时,我们必须传递一个引用,通常情况下可以使用this关键字作为参数,但是也可以使用其他的引用;例如在一个类中有两个属性,当多个线程共享这个类时,必须同步这两个属性;在同一时间,一个线程访问其中一个属性,另外一个线程访问另外一个属性,这样也是没问题的;

在下面的例子中模拟一个电影院,这个电影院有两个荧幕和两个独立的售票窗口,每个售票窗口对应一个荧幕;相互不影响;所以它们余票数目也是相互独立的;

动手实验

1.创建一个cinema,并分别实现两套相互独立的售票和返票的方法

public class Cinema {
    private long vacanciesCinema1;
    private long vacanciesCinema2;

    private final Object controlCinema1,controlCinema2;
    public Cinema(){
        controlCinema1=new Object();
        controlCinema2=new Object();
        vacanciesCinema1=20;
        vacanciesCinema2=20;
    }

    // It uses the controlCinema1 object to control the access to
    // the synchronized block of code
    public boolean sellTickets1 (int number) {
        synchronized (controlCinema1) {
            if (number<vacanciesCinema1) {
                vacanciesCinema1-=number;
                return true;
            } else {
                return false;
            }
        }
    }

    // It uses the controlCinema2 object to control the access to
    // the synchronized block of code
    public boolean sellTickets2 (int number){
        synchronized (controlCinema2) {
            if (number<vacanciesCinema2) {
                vacanciesCinema2-=number;
                return true;
            } else {
                return false;
            }
        }
    }
    // It uses the controlCinema1 object to control the access to
    // the synchronized block of code
    public boolean returnTickets1 (int number) {
        synchronized (controlCinema1) {
            vacanciesCinema1+=number;
            return true;
        }
    }
    // It uses the controlCinema2 object to control the access to
    // the synchronized block of code
    public boolean returnTickets2 (int number) {
        synchronized (controlCinema2) {
            vacanciesCinema2+=number;
            return true;
        }
    }

    public long getVacanciesCinema1() {
        return vacanciesCinema1;
    }
    public long getVacanciesCinema2() {
        return vacanciesCinema2;
    }

}
2.创建两个售票窗

(1)

public class TicketOffice1 implements Runnable {
    private Cinema cinema;
    public TicketOffice1 (Cinema cinema) {
        this.cinema=cinema;
    }
    @Override
    public void run() {
        cinema.sellTickets1(3);
        cinema.sellTickets1(2);
        cinema.sellTickets2(2);
        cinema.returnTickets1(3);
        cinema.sellTickets1(5);
        cinema.sellTickets2(2);
        cinema.sellTickets2(2);
        cinema.sellTickets2(2);
    }
}
(2)
public class TicketOffice2 implements Runnable {
    private Cinema cinema;
    public TicketOffice2(Cinema cinema) {
        this.cinema=cinema;
    }
    @Override
    public void run() {
        cinema.sellTickets2(2);
        cinema.sellTickets2(4);
        cinema.sellTickets1(2);
        cinema.sellTickets1(1);
        cinema.returnTickets2(2);
        cinema.sellTickets1(3);
        cinema.sellTickets2(2);
        cinema.sellTickets1(2);
    }
}
3.Main方法

public class Main {
    public static void main(String[] args) {
        Cinema cinema=new Cinema();
        TicketOffice1 ticketOffice1=new TicketOffice1(cinema);
        Thread thread1=new Thread(ticketOffice1,"TicketOffice1");

        TicketOffice2 ticketOffice2=new TicketOffice2(cinema);
        Thread thread2=new Thread(ticketOffice2,"TicketOffice2");

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Room 1 Vacancies: %d\n",cinema.getVacanciesCinema1());
        System.out.printf("Room 2 Vacancies: %d\n",cinema.getVacanciesCinema2());
    }
}

运行结果:

Room 1 Vacancies: 5
Room 2 Vacancies: 6

要点

JVM确保一个线程只能访问其中一个被同步的同一个对象的代码块(这里是说的是对象,而不是类),在这个例子中,vacanciesCinema1,vacanciesCinema2这两个对象控制访问对应的属性,所以每次只能有一个线程修改一个属性;两个线程也可以同时运行,分别修改对应的属性;



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值