`
dingchd
  • 浏览: 15675 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

层次业务模型的同步锁设计

    博客分类:
  • java
阅读更多

考虑以下情形:一个控制中心对一些资源进行操作,资源之间的关系为层级,如下图uml

 

基地》车间》工作台》工作流

 

每一个对象都包含一些操作,比如基地:建造基地、升级基地、销毁基地、创建车间。。。

车间:建造车间、升级车间、销毁车间、创建工作台。。。

工作台。。。工作流。。。

 

1.不同的车间之间的操作可并行执行,同一车间下的不同工作台可并行操作,同一工作台下的不同操作需要同步执行,若车间内某个工作台正在执行某个操作,那么该车间将同步该操作后才可对该车间进行操作。

 

2.操作未必是针对单一元素,比如车间A的工作台123以及车间B的工作台456的升级操作需要同步,即串行升级,此时若车间A的工作台7需要操作则不受其影响,车间B的工作台8同样,但对车间A、车间B、甚至其基地O的操作则需要等待升级操作结束后

 

 

现在需要设计一个锁的模型来实现以上层次业务模型的同步/并行处理。

 

以上可分层次的业务模型中,可使用树来描述,树的叶子节点为操作,一个操作的描述为自根到叶子节点的路径,如果一个操作涉及多个叶子节点,则该操作描述为自根到该叶子节点s的子树。

 

定义执行:一次针对某个操作集合的执行

定义操作的边界:一次执行涉及的操作叶子节点的父亲集合

定义操作锁:一个次将所有边界节点加锁

 

规律:如果一个边界节点加锁,那么该边界节点的所有前继(父亲结合),和后继(孩子集合)均不能加锁

 

 

代码如下:

 

package flowlock;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 可分层业务模型锁, 业务描述格式为xml
 * 
 * @author dingchd
 * 
 */
public class TreeLock {
	private static final int TIME_WAIT_UNIT = 500;

	private TreeNode root = new TreeNode("root", "root");
	private Map<String, List<TreeNode>> cacheTreeNode = new HashMap<String, List<TreeNode>>();

	// 全局tree的锁
	private Lock globalLock = new ReentrantLock();

	/**
	 * 锁操作子集
	 * 
	 * @param tokenxml
	 *            操作子集的json描述
	 * @throws Exception
	 *             中断、解析失败
	 */
	public void lock(String tokenxml) throws Exception {
		tryLock(tokenxml, -1);
	}

	/**
	 * 锁操作子集,超时退出
	 * 
	 * @param tokenxml
	 * @param timeout
	 * @return 锁定成功返回true
	 * @throws Exception
	 *             中断 、解析失败
	 */
	public boolean tryLock(String tokenXml, int timeout) throws Exception {
		long curTime = System.currentTimeMillis();

		TreeNode node = convert(tokenXml);

		List<TreeNode> borderNodes = null;

		try {
			globalLock.lock();
			borderNodes = combinTree(node); // 合并操作空间
			cacheTreeNode.put(tokenXml, borderNodes);
		} finally {
			globalLock.unlock();
		}

		boolean success = false;
		List<TreeNode> waitNodes = null;
		for (;;) {
			try {
				globalLock.lock();

				waitNodes = getWaitNodes(borderNodes);

				// 如果当前所有预加锁的边界节点的所有前继和后继中不存在边界节点
				if (waitNodes.isEmpty()) {
					for (TreeNode borderNode : borderNodes) {
						borderNode.setLock(true);
					}
					success = true;
					break;
				}
			} finally {
				globalLock.unlock();
			}

			// 等待已存在的边界节点释放
			boolean needWait = false;
			for (TreeNode waitNode : waitNodes) {
				if (waitNode.isLocked()) {
					needWait = true;
					break;
				}
			}

			// 等待并进行超时检测
			if (needWait) {
				Thread.sleep(TIME_WAIT_UNIT);
				if (timeout != -1
						&& System.currentTimeMillis() - curTime > timeout) {
					break;
				}
			}
		}

		return success;
	}

	/**
	 * 从操作树获取边界节点
	 * 
	 * @param node
	 * @return
	 */
	private List<TreeNode> getBorders(TreeNode node) {
		List<TreeNode> borders = new ArrayList<TreeNode>();
		Stack<TreeNode> stack = new Stack<TreeNode>();
		stack.push(node);

		while (!stack.isEmpty()) {
			TreeNode curNode = stack.pop();
			TreeNode[] children = curNode.getChildren();
			if (children.length == 0) {
				borders.add(curNode);
			} else {
				for (TreeNode child : children) {
					stack.push(child);
				}
			}

		}
		return borders;
	}

	/**
	 * 解锁
	 * 
	 * @param tokenxml
	 * @throws Exception
	 */
	public void unlock(String tokenxml) throws Exception {
		try {
			globalLock.lock();

			List<TreeNode> borderNodes = cacheTreeNode.remove(tokenxml);
			if (borderNodes == null) {
				throw new Exception("invalid tokenxml " + tokenxml);
			}

			for (TreeNode borderNode : borderNodes) {
				borderNode.setLock(false);
			}
		} finally {
			globalLock.unlock();
		}
	}

	/**
	 * 获取当前所有节点的前继节点中的边界节点
	 * 
	 * @param borderNodes
	 * @return
	 */
	private List<TreeNode> getWaitNodes(List<TreeNode> borderNodes) {
		List<TreeNode> waitNodes = new ArrayList<TreeNode>();

		// 从前继中查找
		for (TreeNode node : borderNodes) {
			TreeNode curNode = node;
			while (curNode != null) {
				if (curNode.isLocked()) {
					waitNodes.add(curNode);
				}
				curNode = curNode.getFather();
			}
		}

		// 从后继中查找
		Stack<TreeNode> stack = new Stack<TreeNode>();
		for (TreeNode node : borderNodes) {
			stack.push(node);
		}

		while (!stack.isEmpty()) {
			TreeNode node = stack.pop();
			TreeNode[] children = node.getChildren();
			for (TreeNode child : children) {
				if (child.isLocked()) {
					waitNodes.add(child);
				} else {
					stack.push(child);
				}
			}
		}

		return waitNodes;
	}

	/**
	 * 合并操作树,返回当前合并node所反映的所有边界节点 该节点可能来自node的后继,也可能来自root的后继,合并中不进行clone操作
	 * 
	 * @param node
	 * @return
	 */
	private List<TreeNode> combinTree(TreeNode node) {
		List<TreeNode> borders = new ArrayList<TreeNode>();
		Queue<TreeNode> queue = new LinkedList<TreeNode>();

		TreeNode cloneRoot = new TreeNode("root", "root");
		cloneRoot.addChild(node);

		queue.add(cloneRoot);
		queue.add(root);

		while (!queue.isEmpty()) {
			TreeNode combinFrom = queue.poll();
			TreeNode combinTo = queue.poll();

			TreeNode[] childrenFrom = combinFrom.getChildren();
			TreeNode[] childrenTo = combinTo.getChildren();

			if (childrenFrom.length == 0) {
				borders.add(combinTo);
			} else {
				/*
				 * 遍历所有合并来源节点的孩子节点,对照合并目标的孩子节点
				 * 如果来源的孩子节点在目标中不存在,则将该节点添加到合并目标节点的孩子列表中 否则入队列,进行下次合并
				 */
				for (TreeNode childFrom : childrenFrom) {
					boolean exist = false;

					TreeNode existNode = null;
					for (TreeNode childTo : childrenTo) {
						if (childTo.equals(childFrom)) {
							exist = true;
							existNode = childTo;
							break;
						}
					}

					if (exist) {
						queue.add(childFrom);
						queue.add(existNode);
					} else {
						// 通过指针添加孩子节点,不进行clone操作,同时提取该节点的所有borders节点
						combinTo.addChild(childFrom);
						childFrom.setFather(combinTo);
						borders.addAll(getBorders(childFrom));
					}
				}
			}
		}

		return borders;
	}

	/**
	 * 将xml转化为tree
	 * 
	 * @param tokenxml
	 * @return
	 * @throws Exception
	 *             解析出错
	 */
	private TreeNode convert(String tokenXml) throws SAXException, IOException,
			Exception {
		ByteArrayInputStream bin = new ByteArrayInputStream(tokenXml.getBytes());
		Element root = DocumentBuilderFactory.newInstance()
				.newDocumentBuilder().parse(bin).getDocumentElement();

		TreeNode nodeRoot = new TreeNode(root.getNodeName(),
				root.getAttribute("id"));

		TreeNode curNode = nodeRoot;
		Element curEle = root;

		Queue<Object> queue = new LinkedList<Object>();
		queue.add(curNode);
		queue.add(curEle);

		while (!queue.isEmpty()) {
			curNode = (TreeNode) queue.poll();
			curEle = (Element) queue.poll();

			NodeList list = curEle.getChildNodes();
			int num = list.getLength();
			for (int i = 0; i < num; i++) {
				Element childEle = (Element) list.item(i);
				TreeNode childNode = new TreeNode(childEle.getNodeName(),
						childEle.getAttribute("id"));

				// 双向链接
				curNode.addChild(childNode);
				childNode.setFather(curNode);

				queue.add(childNode);
				queue.add(childEle);
			}
		}

		return nodeRoot;
	}

	public TreeNode getRoot() {
		return root;
	}

	static class TreeNode {
		private String key;
		private String value;
		private volatile boolean lock;

		private List<TreeNode> child = new ArrayList<TreeNode>();
		private TreeNode father;

		public TreeNode(String key, String value) {
			this.key = key;
			this.value = value;
		}

		public void addChild(TreeNode node) {
			child.add(node);
		}

		public void removeChild(TreeNode node) {
			child.remove(node);
		}

		public TreeNode[] getChildren() {
			TreeNode[] children = new TreeNode[child.size()];
			child.toArray(children);
			return children;
		}

		public String getKey() {
			return key;
		}

		public String getValue() {
			return value;
		}

		public void setLock(boolean lock) {
			this.lock = lock;
		}

		public boolean isLocked() {
			return lock;
		}

		public TreeNode getFather() {
			return father;
		}

		public void setFather(TreeNode father) {
			this.father = father;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null) {
				return false;
			}

			if (obj instanceof TreeNode) {
				TreeNode node = (TreeNode) obj;
				return key.equals(node.getKey())
						& value.equals(node.getValue());
			}

			return false;
		}

		@Override
		public String toString() {
			return key + ":" + value + ":" + hashCode();
		}
	}
}

 

 

分享到:
评论

相关推荐

    WDK 内核模型框架-驱动程序内核

    5. **同步机制**:提供了一系列同步原语,如锁、互斥量等,以确保多线程环境下的正确执行。 ##### KMDF驱动结构 KMDF驱动程序通常包含以下几个关键部分: - **初始化例程**:用于初始化KMDF框架,并注册驱动程序的...

    系统架构师教程.pdf

    - 层次模型、网状模型、关系模型等。 - **3.2.3 关系代数** - 基本运算符(如选择、投影、笛卡尔积等)的应用。 - **3.2.4 数据的规范化** - 第一范式、第二范式、第三范式等规范化过程。 - **3.2.5 反规范化*...

    数据库知识点梳理(适用于初学者和考研学子)

    - 层次模型:以树形结构表示数据,IBM的IMS是典型的层次模型数据库。 3. SQL语言: - DDL(Data Definition Language):定义数据库结构,如CREATE、ALTER、DROP语句。 - DML(Data Manipulation Language):...

    PowerDesigner.v15.0注册码

    这些模型帮助用户从高层次的概念理解到具体的数据库实现,确保了数据的一致性和完整性。例如,通过PDM,用户可以详细定义表结构、字段类型、索引和关系,为数据库的创建和优化提供蓝图。 在PowerDesigner.v15.0中,...

    卡耐基梅隆的SSD7课件

    3. Java并发编程:线程、同步、锁机制,如synchronized、ReentrantLock等,以及并发集合和并发工具类的使用。 4. Spring框架:作为Java企业级应用的主流框架,Spring提供了依赖注入、AOP(面向切面编程)、事务管理...

    数据库原理

    3. **数据结构化**:数据库系统采用统一的数据模型来组织和存储数据,如关系模型、网状模型或层次模型,使数据具有明确的结构和语义。 4. **数据冗余度低**:通过规范化的数据设计,减少了数据重复存储,降低了数据...

    Patterns of Enterprise Application Architecture

    Martin Fowler探讨了如何设计持久层以及如何有效地处理数据库操作和对象状态同步。 此外,书中还探讨了Web应用中的MVC架构模式。MVC是一种将应用程序分为三个核心组件的设计模式,它有助于分离数据(模型)、用户...

    软件架构文档模板

    通过将业务需求置于需求层次-需求方面矩阵中,可以更深入地理解这些需求是如何影响架构设计的,并且识别出四种主要类型的约束:功能性约束、非功能性约束、技术和实施约束、法规和政策约束。 #### 四、架构设计原则...

    数据库系统概论(第四版)课件

    - 数据模型:包括关系模型、层次模型、网络模型等,其中关系模型是最常见的,基于二维表格结构。 2. **关系数据库理论**: - 关系代数:一种形式化的查询语言,用于表示对关系数据库的操作。 - 函数依赖和范式:...

    数据库系统工程师2005年至2011年历年试题分析与解答.pdf

    数据模型是数据库设计的基础,主要包括层次模型、网状模型、关系模型等。考生需要理解各种模型的特点及应用场景。 #### 2. 关系数据库理论 - **关系模型**:了解关系数据库的基本概念,如表、元组、属性等。 - **...

    企业应用架构模式学习笔记-分层和并发

    分层架构是一种常见的软件设计模式,它将应用程序分解为若干个相互独立、职责明确的层次。通常,我们会看到以下几层: 1. **表示层(Presentation Layer)**:与用户交互,负责接收输入和展示结果。 2. **业务逻辑...

    互联网数据库填空.pdf

    52. 非关系模型:基本层次联系是其数据结构单位。 53. 关系操作:集合操作方式,如选择、投影、连接等。 54. 数据库功能:通过数据库查询语言实现。 55. 规范化设计法:迭代和逐步细化的过程。 56. VBS:Visual ...

    Delphi7-程序设计与开发技术大全.pdf

    - **同步机制**:讲解了线程之间的同步问题,包括互斥锁、信号量等。 - **多线程示例**:通过示例展示了如何在 Delphi 中实现多线程编程。 #### 十五、动态链接库与第三方控件使用 - **DLL 使用**:说明了如何在 ...

    JAVA网络通信系统的研究与开发(源代码+论文+开题报告).zip

    关键技术实现可能涉及异步I/O模型(如NIO或AIO)、线程同步机制(如锁、信号量)以及异常处理策略。实验结果与分析则会展示系统的性能指标,如吞吐量、延迟和并发能力,并对比其他解决方案。 源代码是整个项目的...

    JAVA技术61条面向对象设计的经验原则.txt

    - **应用**:优先考虑组合而非继承,利用接口和策略模式来替代过多的继承层次。 #### 原则十一:明确类之间的关系 - **描述**:清晰定义类之间的关系(如依赖、关联、聚合等)。 - **应用**:通过UML图等方式直观...

    zookeeper-3.4.10.tar.gz

    它的设计目标是简单、高效和高可用,使得开发者可以专注于实现业务逻辑,而无需关心底层的复杂协调问题。 二、Zookeeper的设计原理 1. **分布式一致性模型**:Zookeeper基于ZAB(Zookeeper Atomic Broadcast)协议...

    艾德思奇 adSage 2014 软件工程师题

    7. **并发编程**:在多核处理器环境下,理解锁、信号量、条件变量等同步机制,以及死锁和活锁的概念。 8. **大数据处理**:随着互联网广告的数据量激增,了解Hadoop、Spark等大数据处理框架,以及MapReduce编程模型...

    基于综合形式(PAAS—IAAS)的云计算平台的研究与构建.pdf

    5. 大数据处理能力:MapReduce是一种处理大规模数据集的编程模型,它借鉴了Google的文件系统(Google File System)和Chubby锁服务等分布式系统技术。在综合形式的云平台上,需要提供强大的数据处理能力和实时分析...

Global site tag (gtag.js) - Google Analytics