文档章节

【Java并发编程实战】– 使用非依赖属性实现同步

pan_1308
 pan_1308
发布于 2017/09/07 15:01
字数 608
阅读 8
收藏 0

一、概述

当使用 synchronized 关键字 来保护代码块时,必须把对象引用作为 传入参数。

通常情况下,使用 this 关键字来引用执行方法所属的对象,也可以使用其他的对象对其进行引用。一般来说,这些对象就是为了这个目的而创建的。

例如,在类中有两个非依赖属性,它们被多个线程共享,你必须同步每一个变量的访问,但是同一时刻 只允许一个线程访问一个属性变量,其他的某个线程访问另外一个属性变量。

二、实现

示例: 模拟实现 电影院售票场景,有2个 屏幕 和 2个售票处的电影院,一个售票处卖出的一张票,只能用于其中的一个电影院,不能同时用于2个电影院,因此每个电影院的剩余票数是独立的属性。

/**
 * 使用非依赖属性实现同步
 * 电影院
 * 模拟电影院售票情景
 */
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

 

 

© 著作权归作者所有

共有 人打赏支持
pan_1308
粉丝 5
博文 95
码字总数 58819
作品 0
黄冈
私信 提问
Java 使用 happen-before 规则实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的...

stateIs0
01/20
0
0
【死磕Java并发】—– 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。 先来一个总览图: 【高清图,请关注“Java技术驿站”公众号,回复:脑...

chenssy
07/22
0
0
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
04/16
0
0
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一...

huangzd
01/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周五乱弹 —— 这就是不要女朋友的理由

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @狄安娜的猫 :分享丁家鑫的单曲《丁家鑫 - 克罗地亚狂想曲 - 古筝remix》 《丁家鑫 - 克罗地亚狂想曲 - 古筝remix》 手机党少年们想听歌,请...

小小编辑
22分钟前
124
6
CentOS配置Tomcat监听80端口,虚拟主机

Tomcat更改默认端口为80 更改的配置文件是: /usr/local/tomcat/conf/server.xml [root@test-a ~]# vim /usr/local/tomcat/conf/server.xml # 找到 Connector port="8080" protocol="HTTP/1......

野雪球
今天
5
0
《稻盛和夫经营学》读后感心得体会3180字范文

《稻盛和夫经营学》读后感心得体会3180字范文: 一代日本经营之圣稻盛和夫凭借刻苦勤奋的精神以及深植于佛教的商业道德准则,成为了“佛系”企业家的代表人物。在《稻盛和夫经营学》“领导人...

原创小博客
今天
4
0
java框架学习日志-5(常见的依赖注入)

依赖注入(dependency injection) 之前提到控制反转(Inversion of Control)也叫依赖注入,它们其实是一个东西,只是看的角度不同,这章详细说一下依赖注入。 依赖——指bean对象创建依赖于...

白话
今天
5
0
红外接收器驱动开发

背景:使用系统的红外遥控软件没有反应,然后以为自己接线错误,反复测试,结果烧坏了一个红外接收器,信号主板没有问题。所以自己开发了一个红外接收器的python驱动。接线参见https://my.os...

mbzhong
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部