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

Java多线程同步设计中使用Metux

    博客分类:
  • JAVA
 
阅读更多

Mutex是互斥体,广泛地应用在多线程编程中。本文以广为流程的Doug Lea的concurrent工具包的Mutex实现为例,进行一点探讨。在Doug Lea的concurrent工具包中,Mutex实现了Sync接口,该接口是concurrent工具包中所有锁(lock)、门(gate)和条件变量(condition)的公共接口,Sync的实现类主要有:Mutex、Semaphore及其子类、Latch、CountDown、ReentrantLock等。这也体现了面向抽象编程的思想,使我们可以在不改变代码或者改变少量代码的情况下,选择使用Sync的不同实现。下面是Sync接口的定义:


public interface Sync{ public void acquire() throws InterruptedException; //获取许可 public boolean attempt(long msecs) throws InterruptedException; //尝试获取许可 public void release(); //释放许可}


  通过使用Sync可以替代Java synchronized关键字,并提供更加灵活的同步控制。当然,并不是说 concurrent工具包是和Java synchronized独立的技术,其实concurrent工具包也是在synchronized的基础上搭建的,从下面对Mutex源码的解析即可以看到这一点。synchronized关键字仅在方法内或者代码块内有效,而使用Sync却可以跨越方法甚至通过在对象之间传递,跨越对象进行同步。这是Sync及concurrent工具包比直接使用synchronized更加强大的地方。

  注意Sync中的acquire()和attempt()都会抛出InterruptedException,所以使用Sync及其子类时,调用这些方法一定要捕获InterruptedException.而release()方法并不会抛出InterruptedException,这是因为在acquire()和attempt()方法中可能会调用wait()等待其它线程释放锁。而release()在实现上进行了简化,直接释放锁,不管是否真的持有。所以,你可以对一个并没有acquire()的线程调用release()这也不会有什么问题。而由于release()不会抛出InterruptedException,所以我们可以在catch或finally子句中调用release()以保证获得的锁能够被正确释放。比如:


class X{ Sync gate; // ... public void m() {  try  {   gate.acquire();   // block until condition holds   try   {    // ... method body   }   finally { gate.release(); }  }  catch (InterruptedException ex) { // ... evasive action } }}


  Mutex是一个非重入的互斥锁。Mutex广泛地用在需要跨越方法的before/after类型的同步环境中。下面是Doug Lea的concurrent工具包中的Mutex的实现。

 

public class Mutex implements Sync{ /** The lock status **/ protected boolean inuse_ = false; public void acquire() throws InterruptedException {  if (Thread.interrupted()) throw new InterruptedException();//(1)  synchronized(this)  {   try   {    while (inuse_) wait();    inuse_ = true;   }   catch (InterruptedException ex)   {    //(2)    notify();    throw ex;   }  } } public synchronized void release() {  inuse_ = false;  notify(); } public boolean attempt(long msecs) throws InterruptedException {  if (Thread.interrupted()) throw new InterruptedException();  synchronized(this)  {   if (!inuse_)   {    inuse_ = true;    return true;   }   else if (msecs <= 0)    return false;   else   {    long waitTime = msecs;    long start = System.currentTimeMillis();    try    {     for (;;)     {      wait(waitTime);      if (!inuse_)      {       inuse_ = true;       return true;      }      else      {       waitTime = msecs - (System.currentTimeMillis() - start);       if (waitTime <= 0) // (3)        return false;       }     }    }    catch (InterruptedException ex)    {     notify();     throw ex;    }   }  } }}


  为什么要在acquire()和attempt(0方法的开始都要检查当前线程的中断标志呢?这是为了在当前线程已经被打断时,可以立即返回,而不会仍然在锁标志上等待。调用一个线程的interrupt()方法根据当前线程所处的状态,可能产生两种不同的结果:当线程在运行过程中被打断,则设置当前线程的中断标志为true;如果当前线程阻塞于wait()、sleep()、join(),则当前线程的中断标志被清空,同时抛出InterruptedException.所以在上面代码的位置(2)也捕获了InterruptedException,然后再次抛出InterruptedException.

  release()方法简单地重置inuse_标志,并通知其它线程。

  attempt()方法是利用Java的Object.wait(long)进行计时的,由于Object.wait(long)不是一个精确的时钟,所以attempt(long)方法也是一个粗略的计时。注意代码中位置(3),在超时时返回。

  Mutex是Sync的一个基本实现,除了实现了Sync接口中的方法外,并没有添加新的方法。所以,Mutex的使用和Sync的完全一样。在concurrent包的API中Doug给出了一个精细锁定的List的实现示例,我们这儿也给出,作为对Mutex和Sync使用的一个例子:


class Node{ Object item; Node next; Mutex lock = new Mutex(); // 每一个节点都持有一个锁 Node(Object x, Node n) {  item = x;  next = n; }}class List{ protected Node head; // 指向列表的头 // 使用Java的synchronized保护head域 // (我们当然可以使用Mutex,但是这儿似乎没有这样做的必要  protected synchronized Node getHead() { return head; } boolean search(Object x) throws InterruptedException {  Node p = getHead();  if (p == null) return false;  // (这儿可以更加紧凑,但是为了演示的清楚,各种情况都分别进行处理)  p.lock.acquire();  // Prime loop by acquiring first lock.  // (If the acquire fails due to  // interrupt, the method will throw  // InterruptedException now,  // so there is no need for any  // further cleanup.)  for (;;)  {   if (x.equals(p.item))   {    p.lock.release();    // 释放当前节点的锁    return true;   }   else   {    Node nextp = p.next;    if (nextp == null)    {     p.lock.release();     // 释放最后持有的锁     return false;    }    else    {     try     {      nextp.lock.acquire();      // 在释放当前锁之前获取下一个节点的锁     }     catch (InterruptedException ex)     {      p.lock.release();      // 如果获取失败,也释放当前的锁 throw ex;     }     p.lock.release();     // 释放上个节点的锁,现在已经持有新的锁了     p = nextp;    }   }  } } synchronized void add(Object x) {  // 使用synchronized保护head域  head = new Node(x, head); } // ... other similar traversal and update methods ...}

 

分享到:
评论

相关推荐

    线程同步方法--Metux 实例

    总之,“线程同步方法--Metux实例”通过C++的`std::mutex`展示了如何在Metux库中实现线程安全的资源共享,这对于理解和应用多线程编程,特别是在网络编程中,具有很高的实践价值。通过深入学习和实践这个实例,...

    线程同步的6种方式的代码

    常用的线程锁分为一下七种:volatile关键字、Lock锁、System.Threading.Interlocked原子级别操作、Monitor、Metux、ReaderWriterLock、EventWaitHandle同步事件。此次代码中包含了以上除了volatile的测试代码

    lab2_metux_实验说明1

    互斥锁是一种用于多线程或进程同步的机制,它确保在任何时候只有一个线程或进程可以持有锁,从而防止数据竞争。在Linux内核中,互斥锁通过`mutex`结构体实现,主要函数有`mutex_init()`初始化互斥锁,`mutex_lock()`...

    Windows下开箱后即时编译体验RT-Thread 的MDK demo工程,包含互斥量Metux的使用示例(含动静态方式)

    已包含完整的RT-Thread依赖,可直观体验RT-Thread的使用,代码方面主要未使用互斥量Mutex可能存在的问题,以及使用Mutex如何解决问题的完整示例demo。 工程方面已经集成了RT-Thread的源码,配合博文《RT-Thread 体验...

    只需要用一张图片素材文档选择器.zip

    只需要用一张图片素材文档选择器.zip

    浙江大学842真题09-24 不含答案 信号与系统和数字电路

    浙江大学842真题09-24 不含答案 信号与系统和数字电路

    无标题baci和jbaci

    无标题baci和jbaci

    完整的雷达系统仿真程序,完整的雷达系统仿真程序 matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    实体商品销售源码最新优化.zip

    实体商品销售源码最新优化.zip

    戴尔存储MD1400机柜维护操作与安全指导

    内容概要:本文档详细介绍了戴尔存储MD1400机柜的安全注意事项、电源指示灯解释、故障排除方法以及硬件维护步骤,包括卸下和安装直流电源设备、硬盘驱动器和背板的具体操作流程。 适用人群:IT运维人员、数据中心管理员和技术支持工程师。 使用场景及目标:在维护和管理戴尔存储MD1400机柜时作为参考指南,确保正确安装和故障排查,避免安全隐患和设备损坏。 其他说明:文档提供了丰富的图文指导,帮助使用者更好地理解和执行相关操作。

    PyClass 课程计划.zip

    PyClass 课程计划Noisebridge Python 课程每周一晚上 7 点至 9 点(太平洋时间)在旧金山 Noisebridge 二楼电子室举行。自 2024 年 8 月起,该课程目前暂停。请参阅 wiki 页面了解更多信息。本课程免费!如果您希望捐款,请捐赠给 Noisebridge。建议捐款15 美元、50 美元、200 美元以上建议每月捐款每月 10 美元、20 美元、40 美元、80 美元以上所有 Python 课程均遵循Noisebridge 反骚扰政策、 Noisebridge 冲突解决指南和 recurse.org 社交规则课后,我们欢迎您提供反馈! 在此提交表格内容课程课程描述新生阅读迭代次数Noisebridge Python 课程至少早在 2015 年就已经存在,拥有许多不同的讲师和版本。从 2017 年到 2018 年,该课程似乎由Jared Garst负责。(?)。从 2023 年到 2024 年,该课程由Travis Briggs负责。如果您有其他关于此类历史的信息想要分享,请在此处创建 PR、

    自动化部署管道创建的代码库(含 Concourse 和 Jenkins 相关).zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。

    一种新的混合优化算法,即瞬态三角哈里斯鹰优化器(Tthho) matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    1-中国各地万达广场地理分布数据2006-2021-社科数据.zip

    万达广场作为城市综合体的代表,在中国各地的地理分布数据集覆盖了2006至2021年。这些数据详细记录了万达广场的多个关键指标,包括项目名称、项目信息、具体地点、开业时间、商业面积以及精确的经度和纬度。万达广场不仅是商业地产开发的先行者,还以其成熟的商业模式、完善的产业链和丰富的商业资源,在全国范围内形成了独立的大型商圈。这些综合体集购物、餐饮、文化、娱乐等多种功能于一体,对提升城市商业档次、增加就业岗位、创造税收以及丰富群众消费需求等方面产生了显著的社会效益。数据集提供了420条样本,为研究中国区域经济发展特征及其未来趋势提供了宝贵的信息资源。

    正在月下弹琴的古装美女flash场景动画.zip

    正在月下弹琴的古装美女flash场景动画.zip

    理光Ricoh-MP C8003打印机驱动下载

    理光 MP C8003 是一款彩色激光多功能数码复合机。 【基础性能】 打印复印速度:黑白和彩色打印 / 复印速度均可达 80 页每分钟,能够快速高效地完成大量文档的输出任务,有效提高工作效率 分辨率:拥有 1200x4800dpi 的高分辨率,可输出色彩鲜艳、细节丰富、图像清晰的文档和图像,满足专业级的打印和复印需求,尤其适合对色彩精度要求较高的设计图纸、宣传资料等文件的输出 首张输出时间:黑白首张复印时间为 4.7 秒,彩色首张复印时间为 6.3 秒,在启动打印或复印任务时无需长时间等待,可迅速响应,进一步提升工作效率 纸张容量:标准配置的纸张容量为单 2500 页抽屉和双 550 页抽屉,还可通过扩展将纸张容量从 3700 页提升至 8100 页,能够满足不同规模的打印任务需求,减少纸张添加的频率 【功能多样性】 多功能一体:集复印、打印、扫描、传真功能于一身,可满足办公室多样化的文档处理需求,一台设备即可替代多台单一功能的设备,节省空间和成本 扫描功能:具备高速扫描能力,可通过多种扫描至选项将原件扫描并以电子形式分发,支持将扫描后的文件直接发送至个人移动设备

    《The Annotated Transformer》环境配置

    《The Annotated Transformer》环境配置

    基于深度学习resnet50和vgg16卷积神经网络的汉字书法识别项目源码+训练集+测试集 【可用于课设-毕设】

    深度学习大作业基于resnet50和vgg16卷积神经网络的汉字书法识别项目源码+训练集+测试集 操作步骤 将下载的训练集和测试集,解压到工程中 运行对应的data.py文件,进行转录,将原始数据集转录为numpy矩阵,生成data.npy及label.npy 运行对应的train.py进行训练 运行test.py使用训练完成的网络测试。

    直接序列扩频(DSSS) matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    代码

    代码

Global site tag (gtag.js) - Google Analytics