免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9018 | 回复: 15
打印 上一主题 下一主题

用mutex实现semaphore [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-07-18 13:53 |只看该作者 |正序浏览
想了一下,没有办法呢

论坛徽章:
0
16 [报告]
发表于 2015-03-19 23:15 |只看该作者
mutex + condition + conter 可以模拟 semaphore,但是性能差太远。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
15 [报告]
发表于 2015-03-19 17:44 |只看该作者
本帖最后由 windoze 于 2015-03-19 17:47 编辑

用mutex再加上spinlock,就可以实现condition了,具体的代码可以参考
https://github.com/windoze/fibio ... fiber/condition.cpp

不用spinlock的话,用另外一个mutex也是一样的。

论坛徽章:
1
双鱼座
日期:2013-10-22 16:53:00
14 [报告]
发表于 2015-03-19 14:33 |只看该作者
11 楼的实现,主要的问题在于:pthread_mutex_t类型,不能跨线程释放,
也就是说,如果A线程获取了锁,无法用除A线程外的其它线程来释放它,
如果设置mutexattr,且将锁类型设置为 PTHREAD_MUTEX_ERRORCHECK,
会发现unlock wait 会有很多 EPERM 返回,就是基于上面的原因。

mutexsem init 100
mutexsem init 0
mutexsem wait 100
pred produce 0: 522
mutexsem post 1
pthread_mutex_unlock (&cs->cond): Operation not permitted
mutexsem broadcast
mutexsem_post (&product_sem): Operation not permitted
mutexsem wait 1
cred consume 0: 522
mutexsem post 100
mutexsem wait 100
pred produce 1: 704
mutexsem post 1
pthread_mutex_unlock (&cs->cond): Operation not permitted
mutexsem broadcast
mutexsem_post (&product_sem): Operation not permitted
mutexsem wait 1
cred consume 1: 704
mutexsem post 100
mutexsem wait 0
mutexsem sleep

另外,原代码中:
mutex_lock( &sem->unlock );
应为笔误,正确的应该是:
mutex_unlock(&sem->lock); 吧,呵呵

论坛徽章:
0
13 [报告]
发表于 2010-07-24 11:09 |只看该作者
在用户态实现如何实现原子操作?

论坛徽章:
0
12 [报告]
发表于 2007-07-20 18:15 |只看该作者
仔細想了一下,我的代碼和0521的代碼都有不對。。
原帖由 0521 于 2007-7-19 16:40 发表
假设在用户态实现,假设 Mutex 可以跨线程。仅仅实现了一个信号量。
Mutex M_counter;
Mutex *free_queue;
Mutex *peding_queue;
int count = 0;

semaphore_take()
{
    mutex_take(M_counter);
    count--;
    mutex_give(M_counter);
    if (count < 0)
    {
//如果這裡發生綫程切换,去执行 semaphore_give,
//semaphore_give拿不到pending_mutex里的东西,将不会释放锁!!
//接下来信号量仍旧会锁住线程

        mutex_id = get_a_free_mutex();
        append_to_peding_queue(mutex_id);
        mutex_take(mutex_id);
    }
}


semaphore_give()
{
    mutex_take(M_counter);
    count++;
    mutex_give(M_counter);

    mutex_id = get_first_pending_mutex();
    append_to_free_queue(mutex_id);
    mutex_give(mutex_id);
}

论坛徽章:
0
11 [报告]
发表于 2007-07-20 18:03 |只看该作者
大家幫忙看一下,這樣的用mutex模擬semaphore, 有沒問題呢?



  1. typedef struct
  2. {
  3.      mutex_t lock;
  4.      mutex_t wait;
  5.      int count;
  6. } sem_t;

  7. void sem_init( sem_t &sem, int count )
  8. {
  9.     sem->count = count;
  10.     mutex_init( &sem->lock );
  11.     mutex_init( &sem->wait );
  12.     mutex_lock( &sem->wait );
  13. }

  14. void sem_wait( sem_t &sem )
  15. {
  16.     int count;
  17.     mutex_lock( &sem->lock );
  18.     count = --sem->count;
  19.     mutex_lock( &sem->unlock );

  20.     if ( count < 0 )
  21.         mutex_lock( &sem->wait );
  22. }

  23. void sem_post( sem_t &sem )
  24. {
  25.     int count;
  26.     mutex_lock( &sem->lock );
  27.     count = ++sem->count;
  28.     mutex_lock( &sem->unlock );

  29.     if ( count <= 0 )
  30.         mutex_unlock( &sem->wait );
  31. }

  32. void sem_destory( sem_t &sem )
  33. {
  34.     mutex_destroy( &sem->wait );
  35.     mutex_destroy( &sem->lock );
  36. }

复制代码

论坛徽章:
0
10 [报告]
发表于 2007-07-19 17:04 |只看该作者
原帖由 0521 于 2007-7-19 16:40 发表
假设在用户态实现,假设 Mutex 可以跨线程。仅仅实现了一个信号量。

Mutex M_counter;
Mutex *free_queue;
Mutex *peding_queue;
int count = 0;

semaphore_take()
{
    mutex_take(M_counter);
  ...


为了效率,看来需要在系统里维护一个全局mutex queue,
谢谢你,应该可以了,虽然这个全局queue让偶很不爽

论坛徽章:
0
9 [报告]
发表于 2007-07-19 16:40 |只看该作者
假设在用户态实现,假设 Mutex 可以跨线程。仅仅实现了一个信号量。

Mutex M_counter;
Mutex *free_queue;
Mutex *peding_queue;
int count = 0;

semaphore_take()
{
    mutex_take(M_counter);
    count--;
    mutex_give(M_counter);

    if (count < 0)
    {
        mutex_id = get_a_free_mutex();
        append_to_peding_queue(mutex_id);
        mutex_take(mutex_id);
    }
}


semaphore_give()
{
    mutex_take(M_counter);
    count++;
    mutex_give(M_counter);

    mutex_id = get_first_pending_mutex();
    append_to_free_queue(mutex_id);
    mutex_give(mutex_id);
}

论坛徽章:
0
8 [报告]
发表于 2007-07-19 13:41 |只看该作者
理论上mutex可以实现所有的同步原语。
mutex+counter+queue应该可以实现semaphore了
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP