登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Code@Pig Home

喜欢背着一袋Code傻笑的Pig .. 忧美.欢笑.记忆.忘却 .之. 角落

 
 
 

日志

 
 

[pthread] 同步机制(1) ---- mutex & mutex attr  

2009-12-30 09:15:39|  分类: pthread |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
哇,写了好几篇 pthread 的文字,终于讲到同步机制了。这个主题完成,pthread 的所有 API 就讲解完成啦。:-)

mutex 简单使用
mutex(互斥量) 的概念很简单,就是多个线程竞争一个锁。获得锁的线程 pthread_mutex_lock 会立即返回,而其他线程则会 block 在此函数上,直到此锁被 pthread_mutex_unlock 释放。
----------------------------------------
#include <stdio.h>
#include <time.h>
#include <string.h>     // strerror_r
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;

void *mythr(void *arg)
{
        pthread_mutex_lock(&global_mutex);
        printf("thr #%d getlock = %d\n", (int)arg, time(NULL));
        sleep(5);
        pthread_mutex_unlock(&global_mutex);
        return (void *)0;
}

void *mythr2(void *arg)
{
        int ret;
        char buf[80];
        struct timespec t;

        if ( (ret = pthread_mutex_trylock(&global_mutex)) != 0 )
        {
                strerror_r(ret, buf, sizeof(buf));
                printf("trylock fail, %d, %s\n", ret, buf);
        }
        else
        {
                printf("trylock ok\n");         // won't be here
                pthread_mutex_unlock(&global_mutex);
        }

        clock_gettime(CLOCK_REALTIME, &t);
        t.tv_sec += 2;          // wait 2 sec
        if ( pthread_mutex_timedlock(&global_mutex, &t) != 0 )
        {
                strerror_r(ret, buf, sizeof(buf));
                printf("timedlock fail, %d, %s\n", ret, buf);
        }
        else
        {
                printf("timedlock ok\n");               // won't be here
                pthread_mutex_unlock(&global_mutex);
        }

        return (void *)0;
}

int main()
{
        pthread_t pid1, pid2, pid3;

        pthread_create(&pid1, NULL, mythr, (void*)1);
        pthread_create(&pid2, NULL, mythr, (void*)2);

        sleep(1);
        pthread_create(&pid3, NULL, mythr2, (void*)3);

        pthread_join(pid1, NULL);
        pthread_join(pid2, NULL);
        pthread_join(pid3, NULL);
        return 0;
}
----------------------------------------
$ ./a.out
thr #1 getlock = 1262136722
trylock fail, 16, Device busy
timedlock fail, 16, Device busy
thr #2 getlock = 1262136727
----------------------------------------

mutex 的 type
PTHREAD_MUTEX_ERRORCHECK, 一个线程两次 lock 同一个 mutex,则返回 EDEADLK。
PTHREAD_MUTEX_RECURSIVE, 允许一个线程两次 lock 同一个 mutex,不算错误。
PTHREAD_MUTEX_NORMAL, 一个线程两次 lock 同一个 mutex, 不返回错误值,直接 block 住(deadlock)。

----------------------------------------
#include <stdio.h>
#include <string.h> // strerror_r
#include <unistd.h>
#include <pthread.h>

void *mythr1(void *arg)
{
    int ret;
    char buf[80];
    pthread_mutex_t mutex;
    pthread_mutexattr_t mattr;

    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK);    // default type

    pthread_mutex_init(&mutex, &mattr);
    pthread_mutexattr_destroy(&mattr);

    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck mutex, lock fail, %d, %s\n", ret, buf);
    }
    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck, lock fail, %d, %s\n", ret, buf);
    }

    pthread_mutex_unlock(&mutex);
    return (void *)0;
}

void *mythr2(void *arg)
{
    int ret;
    char buf[80];
    pthread_mutex_t mutex;
    pthread_mutexattr_t mattr;

    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);

    pthread_mutex_init(&mutex, &mattr);
    pthread_mutexattr_destroy(&mattr);

    // won't be any error
    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck mutex, lock fail, %d, %s\n", ret, buf);
    }
    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck, lock fail, %d, %s\n", ret, buf);
    }

    pthread_mutex_unlock(&mutex);
    pthread_mutex_unlock(&mutex);
    return (void *)0;
}

void *mythr3(void *arg)
{
    int ret;
    char buf[80];
    pthread_mutex_t mutex;
    pthread_mutexattr_t mattr;

    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL);

    pthread_mutex_init(&mutex, &mattr);
    pthread_mutexattr_destroy(&mattr);

    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck mutex, lock fail, %d, %s\n", ret, buf);
    }

    // deadlock here
    if ( (ret = pthread_mutex_lock(&mutex)) != 0 )
    {
        strerror_r(ret, buf, sizeof(buf));
        printf("errcheck, lock fail, %d, %s\n", ret, buf);
    }

    pthread_mutex_unlock(&mutex);
    return (void *)0;
}

int main()
{
    pthread_t pid1, pid2, pid3;

    pthread_create(&pid1, NULL, mythr1, NULL);
    pthread_create(&pid2, NULL, mythr2, NULL);
    pthread_create(&pid3, NULL, mythr3, NULL);

    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);
    pthread_join(pid3, NULL);
    return 0;
}
----------------------------------------
$ ./a.out
errcheck, lock fail, 11, Resource deadlock avoided
----------------------------------------

mutex 的 process shared
我们可以通过 pthread_mutexattr_getpshared / setpshared 来设置此 mutex 是否允许跨进程访问。
PTHREAD_PROCESS_SHARED, 允许跨进程访问。
PTHREAD_PROCESS_PRIVATE, 不允许,此为默认值。
可惜 FreeBSD 不支持 PTHREAD_PROCESS_SHARED,无法测试其具体的使用方式,估计就是 fork() 之后,共享之。个人觉得还是 win32 的 CreateMutex 允许传入一个 const char * 来标识一个跨进程的 mutex ,用起来比较方便。

  评论这张
 
阅读(2798)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018