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


    转载时请注明出处和作者联系方式
    文章出处:http://www.limodev.cn/blog
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    嵌套锁与装饰模式

    嵌套锁的实现算法

    加锁:

      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);

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

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


    欢迎到Linux mobile development上交流

  • 相关阅读:
    codeforces 455B A Lot of Games(博弈,字典树)
    HDU 4825 Xor Sum(二进制的字典树,数组模拟)
    hdu 1800 Flying to the Mars(简单模拟,string,字符串)
    codeforces 425A Sereja and Swaps(模拟,vector,枚举区间)
    codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)
    HDU 4148 Length of S(n)(字符串)
    codeforces 439D Devu and Partitioning of the Array(有深度的模拟)
    浅谈sass
    京东楼层案例思维逻辑分析
    浅谈localStorage和sessionStorage
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167571.html
Copyright © 2020-2023  润新知