`
阿尔萨斯
  • 浏览: 4262383 次
社区版块
存档分类
最新评论

系统程序员成长计划-并发(三)(下)

 
阅读更多

嵌套锁与装饰模式

嵌套锁的实现算法

加锁:

o如果没有任何线程加锁,就直接加锁,并且记录下当前线程的ID。
o如果是当前线程加过锁了,就不用加锁了,只是将加锁的计数增加一。
o如果其它线程加锁了,那就等待直到加锁成功,后继步骤与第一种情况相同。

解锁:
o如果不是当前线程加的锁或者没有人加锁,那这是错误的调用,直接返回。
o如果是当前线程加锁了,将加锁的计数减一。如果计数大于0,说明当前线程加了多次,直接返回就行了。如果计数为0,说明当前线程只加了一次,则执行解锁动作。

这个逻辑很简单,要做到兼容Locker的接口和平台无关,我们还需要引入装饰模式这个概念。装饰模式的功能是在于不改变对象的本质(接口)的前提下,给对象添加附加的功能。和继承不同的是,它不是针对整个类的,而只是针对单个对象的。装饰这个名字非常直观的表现它的意义:在你自己的显示器上做点了装饰,比如贴上一张卡通画:第一是它没有改显示器的本质,显示器还是显示器。第二是只有你自己的显示器上多了张卡通画,其它显示器没有影响。

这里我们要对一把锁进行装饰,不改变它的接口,但给它加上嵌套的功能。下面我们看看在C语言里的实现方法:

o 创建函数的原型。由于获取当前线程ID的函数是平台相关的,我们要用回调函数来抽象它。

typedef int (*TaskSelfFunc)(void);
Locker* locker_nest_create(Locker* real_locker, TaskSelfFunc task_self);

这里可以看出:传入的是一把锁,返回的还是一把锁,没有改变的接口,但是返回的锁已经具有嵌套调用的功能了。

o 嵌入锁的实现。

私有信息:拥有锁的线程ID、加锁的计数,被装饰的锁和获取当前线程ID的回调函数。

typedef struct _PrivInfo
{
    int owner;
    int refcount;
    Locker* real_locker;
    TaskSelfFunc task_self;
}PrivInfo;

1.实现加锁函数:如果当前线程已经加锁,只是增加加锁计数,否则就加锁。

static Ret  locker_nest_lock(Locker* thiz)
{
    Ret ret = RET_OK;
    PrivInfo* priv = (PrivInfo*)thiz->priv;

    if(priv->owner == priv->task_self())
    {
        priv->refcount++;
    }
    else
    {
        if( (ret = locker_lock(priv->real_locker)) == RET_OK)
        {
            priv->refcount = 1;
            priv->owner = priv->task_self();
        }
    }

    return ret;
}

2.实现解锁函数:只有当前线程加的锁才能解锁,先减少加锁计数,计数为0时才真正解锁,否则直接返回。

static Ret  locker_nest_unlock(Locker* thiz)
{
    Ret ret = RET_OK;
    PrivInfo* priv = (PrivInfo*)thiz->priv;

    return_val_if_fail(priv->owner == priv->task_self(), RET_FAIL);

    priv->refcount--;
    if(priv->refcount == 0)
    {
        priv->owner = 0;
        ret = locker_unlock(priv->real_locker);
    }

    return ret;
}

o使用方法。除了创建方法稍有不同外,调用方法完全一样。

    Locker* locker = locker_pthread_create();
    Locker* nest_locker = locker_nest_create(locker, (TaskSelfFunc)pthread_self);
    DList*  dlist = dlist_create(NULL, NULL, nest_locker);

装饰模式最有用的地方在于,它给单个对象增加功能,但不是影响调用者,即使加了多级装饰,调用者也不用关心。

本节示例代码请到这里下载。

分享到:
评论

相关推荐

    积分管理系统java源码-DocCollection:文档集

    积分管理系统java源码 ...汇总java生态圈常用技术框架、开源中间件,系统架构、数据库、大公司架构案例、常用三方类库、项目管理、线上问题排查、个人成长、思考等知识 TheAlgorithms Github地址: 算法与数据结构

    百度地图开发java源码-JavaPlan:Java学习、进阶、面试、架构师成长之路,Java程序员进阶大牛的核心知识体系

    本项目大部分内容来自我近几年的收集和整理,根据计划将主要包含:Java相关知识、网络编程、并发编程、微服务、Linux、数据库、数据结构、算法等知识内容。本人对有深度的系列文章情有独钟,所以整理过程中会更加...

    java8集合源码分析-JavaBooks:书籍

    java8 集合源码分析 JavaBooks ...12.程序员成长 高效程序员的45个习惯 99.其他 详细推荐书单 基础入门 Java编程思想(Thinking in Java)、Java核心技术(Core Java) ,Java8 实战(Java in action),Eff

    java版飞机大战源码-java-club:Java程序员所需要掌握的核心知识都在这里。。。。alittledaily~

    如果我们通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。 在工作中发现我身边的人真的就是实力越强的越努力,最高级的自律,享受孤独。 整理收录一份Java核心知识图谱 ...

    从 Swift 到机器学习 - 王巍.pdf

    这也提醒了我们,作为一名程序员,不仅需要掌握技术知识,还需要关心职业发展和个人成长。 资源链接: * WWDC 2018 Session 703:https://developer.apple.com/videos/play/wwdc2018/703/ * Core ML Specification...

    百度地图毕业设计源码-Java-Notes:2020Java快速成长学习路线,从0到1的过程,打破你知识的盲区,渐渐爱上Java,我想对还是小

    Java快速成长学习路线 @学习路线根据黑马程序员学习路线改编 Part1: Java基础&Web基础 Java基础 面向对象思想 集合框架 IO流 多线程与并发 异常处理 网络编程 数据库 MySQL Oracle JDBC C3P0 Druid 前端技术 HTML ...

    java版商城源码下载-awesome-jp:百宝箱

    生态圈常用技术框架、开源中间件,系统架构、数据库、大公司架构案例、常用三方类库、项目管理、线上问题排查、个人成长、思考等知识 :该项目是一系列小而专注的教程 - 每个教程都涵盖 Java 生态系统中单一且定义...

    Java核心技术 第12版 开发基础+高级特性 英文原版

    伴随着Java的成长,《Java核心技术》从第1版到第11版一路走来,得到了广大Java程序设计人员的青睐,成为一本畅销不衰的Java经典图书。 本书经全面修订,以涵盖Java 17的新特性。新版延续之前版本的优良传统,用数百...

    亮剑.NET深入体验与实战精要2

    本书集实用性、思想性、趣味性于一体,内容共分为技术基础总结、系统架构设计思想及项目实战解析三部分,随书所附光盘收录大量实例代码及独家披露的商业系统,供读者参考学习。 本书适合于.NET初、中级开发人员参考...

    亮剑.NET深入体验与实战精要3

    本书集实用性、思想性、趣味性于一体,内容共分为技术基础总结、系统架构设计思想及项目实战解析三部分,随书所附光盘收录大量实例代码及独家披露的商业系统,供读者参考学习。 本书适合于.NET初、中级开发人员参考...

    leetcode中国-xvyqiu:xvyqiu

    Java开发者的高级知识,涵盖高并发、分布式系统、高可用、微服务、海量数据处理等。 2 很棒的编程书籍列表。 3 Java 虚拟机基本原理的总结。 4 任何编程语言的 LeetCode 解决方案。 5 程序员面试问题合集。 主要内容...

    leetcode中国-woaker.github.io:woaker的个人博客

    Java开发者的高级知识,涵盖高并发、分布式系统、高可用、微服务、海量数据处理等。 2 很棒的编程书籍列表。 3 Java 虚拟机基本原理的总结。 4 任何编程语言的 LeetCode 解决方案。 5 程序员面试问题合集。 主要内容...

    py12306抢票开源库,假期抢票难,加脚本直接上强度!

    然而,面对庞大的用户群体和高并发的购票请求,传统的购票系统可能会遇到一系列的挑战,例如系统崩溃、购票失败等问题。 为了解决这些问题,一款名为py12306的高效分布式多账号、多任务购票系统应运而生。 本文讲...

Global site tag (gtag.js) - Google Analytics