




已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java Monitor Pattern本文从典型的 Monitor Object 设计模式入手,从一个新的视角,来探讨 Java 语言的同步机制.本文将从两个方面进行阐述:1、使用 C 语言来描述 Monitor Object 设计模式.Java 对于这样一个典型的模式做了很好的语言层面的封装,因此对于 Java 的开发者来说,很多关于该模式本身的东西被屏蔽掉了.本文试图使用 Native C 语言,帮助读者从本质上对 Monitor object 设计模式有一个更全面的认识.2、结合 C 版本的 Monitor Object 设计模式,引领读者对于 Java 同步机制有一个更深刻的认识,帮助读者正确有效地使用 Java 同步机制.预备知识在开始正式讨论之前,需要了解一些预备知识.什么是 RAII资源获取即初始化(RAII, Resource Acquisition Is Initialization)是指,在一个对象的构造函数中获得资源 , 并且在该对象的析构函数中释放它.这个资源可以是对象、内存、文件句柄或者其它类型.实现这种功能的类,我们就说它采用了资源获取即初始化(RAII)的方式. RAII 是一种很典型的语言惯用法,被很多的 OO 语言所使用,下面是 C 的例子.清单 1. RAII Using Cclass Raii public: / Store a pointer to the resource and initialize the resource. Raii(Resource &resource) :m_pRes (&resource) m_pRes-initialize (); / Close the resource when the execution goes out of scope. virtual Raii() m_pRes-close (); private: / Pointer to the resource were managing. Resource *m_pRes; / . maybe need disallow copying and assignment . ;使用 RAII 的好处是:析构函数由系统自动调用,这样可以帮助我们自动地隐式释放我们所获取的资源.事情上,我们熟知的很多C技术都用到了这一设计模式,比如:智能指针 (Smart Pointer),以及我们接下来要讨论的范围锁 (Scoped Lock) .不同于 C ,Java 对象没有析构函数,Java System 提供了 GC 来管理内存资源.而对于像数据库连接,Sockets 这样类型的资源, Java 提供了 finalize() 来处理.但是,请注意,Java 的 finalizer 与 C 的析构函数是不同的,finalize() 函数由 GC 异步地在某个恰当的时候调用,我们不能等同地使用 finalize() 来实现 C 里的 RAII .通常的做法是使用 Java 提供的 finally 语句块.清单 2. RAII Using JavaMyResource res = null;try res = new MyResource(); / Use the resource finally /At exit point, close the resource. if (res != null) res.close(); 什么是区域锁 (Scoped Lock)区域锁是指线程执行进入一个区域时,一个锁将自动被获取,当该线程执行离开这个区域时,这个锁将被自动释放. C 区域锁的实现使用了 RAII 技术 , 实现如下.清单 3. Scoped Lock Using Ctemplate class Guard public: / Store a pointer to the lock and acquire the lock. Guard (LOCK &lock) :m_pLlock (&lock), m_bOwner (false) m_pLlock-acquire (); m_bOwner = true; / Release the lock when the guard goes out of scope, / but only if succeeded. virtual Guard () if (m_bOwner) m_pLlock-release (); private: / Pointer to the lock were managing. LOCK *m_pLlock; / Records if the lock is held by this object. bool m_bOwner; / . maybe need disallow copying and assignment . ;Guard 是一个模板类,LOCK 类型指的是对操作系统提供的线程锁的抽象,比如,在 Windows 平台上,LOCK 可以是对 CRITICAL_SECTION 的封装.Java 对于区域锁模式在语言层面上已经做了封装,所以对于 Java 开发者来说,不必像 C 这样来开发自己的区域锁类,这就是我们所熟知的 synchronized 关键字.清单 4. Scoped Lock Using Javapublic int scopedLockSample() synchronized(this) try /do some work catch( MyException1 e) /no need release lock explicitly return -1; catch( MyException2 e) /no need release lock explicitly return -2; /other exceptions handling. return 0; synchronized 保证在进入该区域后,获得对象锁,不管最终该函数从哪里退出,该对象锁都会被正确释放.什么是条件变量 (Condition Variables)条件变量通常被一个线程用于使自己等待,直到一个涉及共享数据的条件表达式到达特定的状态.当另外的协作线程指示共享数据的状态已发生变化,调度器就唤醒在该条件变量上挂起的线程.于是新唤醒的线程重新对它的条件表达式进行求值,如果共享数据已到达合适状态,就恢复处理.以下是条件变量的 C 实现.清单 5. Thread Condition Using Cclass Thread_Condition public: / Initialize the condition variable and associate it with the specified lock Thread_Condition (const Thread_Mutex &m) :m_obMutex(m) cond_init (&cond_, USYNC_THREAD, 0); / Destroy the condition variable. virtual Thread_Condition () cond_destroy (&cond_); / Wait for the to be notified / or until has elapsed. / if = 0 then wait indefinitely. void wait (Time_Value *timeout = 0) cond_timedwait(&cond_, &m_obMutex.m_lock,timeout = 0 ? 0 : timeout-msec (); / Notify one thread waiting on . void notify () cond_signal (&cond_); / Notify all threads waiting on . void notify_all () cond_broadcast (&cond_); private: / Solaris condition variable. cond_t cond_; / Reference to mutex lock. const Thread_Mutex &m_obMutex; ;Thread_Condition 的实现与操作系统提供的 API 密切相关,以上的例子是基于 Solaris condition variable API 的面向对象的封装.另外,这里的 Thread_Mutex 类型是对操作系统提供的线程锁的面向对象的封装 (Thread_Mutex 类型就是 Guard 模板参数 LOCK 所指向的类型 ) .而对于 Java,问题就变得简单很多,你不需要去封装自己的条件变量类,Java 的根类 Object 提供了 wait/notify/notifyAll 方法给开发者,很容易使用,这个我们在后面的讨论中会看到.Monitor Object 设计模式 C 描述我们将从以下几个方面来讨论 Monitor Object 模式.问题描述我们在开发并发的应用时,经常需要设计这样的对象,该对象的方法会在多线程的环境下被调用,而这些方法的执行都会改变该对象本身的状态.为了防止竞争条件 (race condition) 的出现,对于这类对象的设计,需要考虑解决以下问题: 在任一时间内,只有唯一的公共的成员方法,被唯一的线程所执行. 对于对象的调用者来说,如果总是需要在调用方法之前进行拿锁,而在调用方法之后进行放锁,这将会使并发应用编程变得更加困难.合理的设计是,该对象本身确保任何针对它的方法请求的同步被透明的进行,而不需要调用者的介入. 如果一个对象的方法执行过程中,某些条件不能满足而阻塞,应该允许其它的客户端线程的方法调用可以访问该对象.我们使用 Monitor Object 设计模式来解决这类问题:将被客户线程并发访问的对象定义为一个 monitor 对象.客户线程仅仅通过 monitor 对象的同步方法才能使用 monitor 对象定义的服务.为了防止陷入竞争条件,在任一时刻只能有一个同步方法被执行.每一个 monitor 对象包含一个 monitor 锁,该锁被同步方法用于串行访问对象的行为和状态.此外,同步方法可以根据一个或多个与 monitor 对象相关的 monitor conditions 来决定在何种情况下挂起或恢复他们的执行.结构在 Monitor Object 模式中,主要有四种类型的参与者: 监视者对象 (Monitor Object): 负责定义公共的接口方法,这些公共的接口方法会在多线程的环境下被调用执行. 同步方法:这些方法是监视者对象所定义.为了防止竞争条件,无论是否同时有多个线程并发调用同步方法,还是监视者对象含有多个同步方法,在任一时间内只有监视者对象的一个同步方法能够被执行. 监视锁 (Monitor Lock): 每一个监视者对象都会拥有一把监视锁. 监视条件 (Monitor Condition): 同步方法使用监视锁和监视条件来决定方法是否需要阻塞或重新执行.执行序列图在监视者对象模式中,在参与者之间将发生如下的协作过程:1、 同步方法的调用和串行化.当客户线程调用监视者对象的同步方法时,必须获取它的监视锁.只要该监视者对象有其他同步方法正在被执行,获取操作便不会成功.在这种情况下,客户线程将被阻塞直到它获取监视锁.当客户线程成功获取监视锁后,进入临界区,执行方法实现的服务.一旦同步方法完成执行,监视锁会被自动释放,目的是使其他客户线程有机会调用执行该监视者对象的同步方法.2、 同步方法线程挂起.如果调用同步方法的客户线程必须被阻塞或是有其他原因不能立刻进行,它能够在一个监视条件上等待,这将导致该客户线程暂时释放监视锁,并被挂起在监视条件上.3、监视条件通知.一个客户线程能够通知一个监视条件,目的是为了让一个前期使自己挂起在一个监视条件上的同步方法线程恢复运行.4、同步方法线程恢复.一旦一个早先被挂起在监视条件上的同步方法线程获取通知,它将继续在最初的等待监视条件的点上执行.在被通知线程被允许恢复执行同步方法之前,监视锁将自动被获取.图 1 描述了监视者对象的动态特性.示例在本节中,我们将使用监视者对象设计模式来解决一个实际的问题.这是一个典型的生产者/消费者模式问题.假定我们有一个固定长度的消息队列,该队列会被多个生产者/消费者线程所操作,生产者线程负责将消息放入该队列,而消费者线程负责从该对列中取出消息.清单 6. Message_Queue.hclass Message_Queue public: enum MAX_MESSAGES = 100/* . */ ; / 消息队列中最大消息个数。当达到这个数量时,消息队列为满状态(full)。 Message_Queue(size_t max_messages = MAX_MESSAGES); virtual Message_Queue(); / 将消息放在队列的末尾。如果队列已满。阻塞并的不等待 /* synchronized */ void put (const Message &msg); / 从队列中获得消息。如果队列为空,阻塞直到非空 /* synchronized */ Message get(); / /检查消息队列是否为空 /* synchronized */ bool empty () const; / 检查消息队列是否已满 /* synchronized */ bool full () const; private: / 注意:内部方法是不同步的 void put_i (const Message &msg); Message get_i (); bool empty_i () const; bool full_i () const; private: /省略队列的内部结构。可以是循环队列或链表 size_t message_count_; size_t max_messages_; /在并发访问期间,监视锁队列内部状态,防止竞争条件 Mutable Thread_Mutex monitor_lock_; /条件变量和监视锁联合使用使同步方法线程等待直到消息队列不空 Thread_Condition not_empty_; /条件变量和监视锁联合使用使同步方法线程等待直到消息队列未满 Thread_Condition not_full_;单 7. Message_Queue.cpp#include Message_Queue.hMessage_Queue:Message_Queue (size_t max_messages) :not_full_(monitor_lock_), not_empty_(monitor_lock_), max_messages_(max_messages), message_count_(0) bool Message_Queue:empty () const Guard guard (monitor_lock_); return empty_i ();bool Message_Queue:full () const Guard guard (monitor_lock_); return full_i ();void Message_Queue:put (const Message &msg) / Use the Scoped Locking idiom to acquire/release the upon/ entry/exit to the synchronized method. Guard guard (monitor_lock_);/ 等待直到队列满 while (full_i () /释放监视锁,挂起调用线程,等待队列中有多余空间 / 当等待返回时,自动获得监视锁 not_full_.wait (); / 在消息队列尾部加入消息 put_i (msg); / 通知在get时等待的线程消息队列中有消息到达 not_empty_.notify (); / 析构guard释放监视锁。Message Message_Queue:get () / Use the Scoped Locking idiom to acquire/release the upon / entry/exit to the synchronized method. Guard guard (monitor_lock_); /消息队列为空时等待 while (empty_i () / 释放监视锁,挂起调用线程等待新的消息到来,wait返回时重新获得监视锁。 not_empty_.wait (); / 获取消息队列中第一次消息,更新消息个数 Message m = get_i (); / 通知在PUT中等待的线程,消息队列中有空间可用(消息队列未满) not_full_.notify (); return m; / / 析构guard释放监视锁。bool Message_Queue:empty_i () const return message_count_ = 0; bool Message_Queue:full_i () const return message_count_ = max_messages_; Message_Queue:Message_Queue() Monitor Object Java 实践认识 Java Monitor ObjectJava Monitor 从两个方面来支持线程之间的同步,即:互斥执行与协作. Java 使用对象锁 (使用 synchronized 获得对象锁)保证工作在共享的数据集上的线程互斥执行 , 使用 notify/notifyAll/wait 方法来协同不同线程之间的工作.这些方法在 Object 类上被定义,会被所有的 Java 对象自动继承.实质上,Java 的 Object 类本身就是监视者对象,Java 语言对于这样一个典型并发设计模式做了内建的支持.不过,在 Java 里,我们已经看不到了我们在 C 一节所讨论的区域锁与条件变量的概念.下图很好地描述了 Java Monitor 的工作机理.图 2. Java Monitor线程如果获得监视锁成功,将成为该监视者对象的拥有者.在任一时刻内,监视者对象只属于一个活动线程 (Owner) .拥有者线程可以调用 wait 方法自动释放监视锁,进入等待状态.示例在本节,我们将用 Java Monitor 来重新解决用 C 实现的生产者 / 消费者模式问题.清单 8. Message Classpublic class Message private static int OBJ_COUNT = 0; public int obj_index_; Message() synchronized(Message.class) OBJ_COUNT ; obj_index_ = OBJ_COUNT; Override public String toString() return message obj_index_ ; 清单 9. MessageQueue Classpublic class MessageQueue private int message_count_; private int max_messages_; private Message buffer_; private int in_ = 0, out_ = 0; public MessageQueue(int max_messages) max_messages_ = max_messages; message_count_ = 0; buffer_ = new Messagemax_messages_; synchronized boolean full () return full_i (); synchronized void put (Message msg) while (full_i () try System.out.println(thread+Thread.currentThread().getId()+ release monitor lock, wait for space in the queue); wait(); catch (InterruptedException e) /do something. finally /do something. /end while. put_i(msg); notifyAll(); synchronized Message get() while (empty_i () try System.out.println(thread+Thread.currentThread().getId() + release monitor lock, wait for message in the queue); wait(); catch (InterruptedException e) /do something. finally /do something. /end while. Message m = get_i (); notifyAll(); return m; private boolean empty_i () return message_count_ = 0; private boolean full_i () return message_count_ = max_messages_; private void put_i (Message msg) System.out.println(thread +Thread.currentThread().getId() + put message to the queue)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025福建三明市属国企招聘项目负责人笔试历年参考题库附带答案详解
- 2025甘肃中电瓜州风力发电有限公司校园招聘笔试历年参考题库附带答案详解
- 2025河南南阳市西峡县宜居城镇工程建设有限公司招聘(第七号)笔试历年参考题库附带答案详解
- 2025年福建一建物业管理有限公司招聘劳务派遣工作人员笔试历年参考题库附带答案详解
- 2025安徽淮南焦岗湖投资集团有限公司政府投资工程审计人员招聘拟聘用人员笔试历年参考题库附带答案详解
- 2025广西河池市招聘中小学幼儿园教师565人模拟试卷及答案详解(名师系列)
- 2025广西柳州市柳江中学参加广西师范大学2025届研究生毕业生春季专场双选会招聘11人考前自测高频考点模拟试题及答案详解(易错题)
- 2025年上半年全省事业单位公开招聘工作人员(含教师)笔试南充考区模拟试卷及答案详解参考
- 2025江苏盐城工业职业技术学院招聘专职辅导员6人考前自测高频考点模拟试题附答案详解(考试直接用)
- 2025年甘肃省卫生健康委系统招聘工作人员网上缴费考前自测高频考点模拟试题附答案详解(黄金题型)
- 巡检管理制度燃气版
- 2024年企业全面预算管理教材模板
- 新生儿洗胃操作课件
- 2024行政办事员职业资格认证理论考核试题
- 国际工程风险管理案例分析
- 中医眼科学瞳神疾病上
- 运动中的攻击性行为
- 欧美钢结构案例-花旗银行中心工程危机
- 从“管理型”到“服务型”:中职学校行政组织的模式转型与对策研究
- 中华人民共和国档案法修订宣传课件
- 工具式型钢悬挑脚手架施工工法
评论
0/150
提交评论