当使用 synchronized 关键字 来保护代码块时,必须把对象引用做为 传入参数。java
一般状况下,使用 this 关键字来引用执行方法所属的对象,也能够使用其余的对象对其进行引用。通常来讲,这些对象就是为了这个目的而建立的。ide
例如,在类中有两个非依赖属性,它们被多个线程共享,你必须同步每个变量的访问,可是同一时刻 只容许一个线程访问一个属性变量,其余的某个线程访问另一个属性变量。测试
示例: 模拟实现 电影院售票场景,有2个 屏幕 和 2个售票处的电影院,一个售票处卖出的一张票,只能用于其中的一个电影院,不能同时用于2个电影院,所以每一个电影院的剩余票数是独立的属性。this
/** * 使用非依赖属性实现同步 * 电影院 * 模拟电影院售票情景 */ public class Cinema { private long vacanciesCinema1; // 电影院1 的票 private long vacanciesCinema2; // 电影院2 的票 // 2个对象属性 private final Object controlCinema1, controlCinema2; public Cinema(){ controlCinema1 = new Object(); controlCinema2 = new Object(); vacanciesCinema1 = 20; vacanciesCinema2 = 20; } // 第一个电影院卖票 -> 使用 controlCinema1对象来控制同步代码块的访问. public boolean sellTickets1(int num){ synchronized (controlCinema1) { if(vacanciesCinema1 < num){ return false; } vacanciesCinema1 -= num; return true; } } // 第二个电影院卖票 -> 使用 controlCinema2对象来控制同步代码块的访问. public boolean sellTickets2(int num){ synchronized (controlCinema2) { if(vacanciesCinema2 < num){ return false; } vacanciesCinema2 -= num; return true; } } //第一个电影院退票 public boolean returnTickets1(int num){ synchronized (controlCinema1) { vacanciesCinema1 += num; return true; } } //第二个电影院退票 public boolean returnTickets2(int num){ synchronized (controlCinema2) { vacanciesCinema2 += num; return true; } } public long getVacanciesCinema1() { return vacanciesCinema1; } public long getVacanciesCinema2() { return vacanciesCinema2; } }
/*** * 售票处1 */ public class TicketOffice1 implements Runnable{ private Cinema cinema; public TicketOffice1(Cinema cinema) { this.cinema = cinema; } public void run() { cinema.sellTickets1(2); cinema.sellTickets1(1); cinema.sellTickets2(3); cinema.sellTickets2(2); cinema.returnTickets1(1); cinema.returnTickets2(2); } }
/*** * 售票处2 */ public class TicketOffice2 implements Runnable{ private Cinema cinema; public TicketOffice2(Cinema cinema){ this.cinema = cinema; } @Override public void run() { cinema.sellTickets1(1); cinema.sellTickets2(2); cinema.sellTickets1(5); cinema.sellTickets1(3); cinema.sellTickets2(4); cinema.returnTickets1(2); cinema.returnTickets2(1); } }
/** * 测试 */ public class CinemaTest { public static void main(String[] args) { Cinema cinema = new Cinema(); TicketOffice1 ticketOffice1 = new TicketOffice1(cinema); TicketOffice2 ticketOffice2 = new TicketOffice2(cinema); Thread thread1 = new Thread(ticketOffice1); Thread thread2 = new Thread(ticketOffice2); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.err.println("电影院1 剩余:" + cinema.getVacanciesCinema1()); System.err.println("电影院2 剩余:" + cinema.getVacanciesCinema2()); } } //console结果: 电影院1 剩余:11 电影院2 剩余:12