多进程共享的pthread_mutex_t

设置方式

  1. 要有一片多进程能一起访问的共享内存。共享内存如何获得本文不做介绍,请自行google。
  2. 共享内存划一段大小为sizeof(pthread_mutex_t)的内存备用,记这片内存为mutex_reserve。把这片内存初始化为全0。
  3. 用pthread_mutex_t的指针mutex_p指向mutex_reserve。
  4. 构造phtread_mutex_t的初始化属性结构体pthread_mutexattr_t attr。
  5. 设置attr为PTHREAD_PROCESS_SHARED。
  6. 用attr初始化mutex_p指向的phtread_mutex_t。

答疑

1.用NULL初始化共享内存中的pthread_mutex_t可以吗?也就是省略掉步骤4和5。

答:不完全可以。不用被设置为PTHREAD_PROCESS_SHARED的attr初始化mutex,mutex也能保证互斥:实验表明,如果进程不调用sleep(),省略与不省略步骤4-5的结果是一样的,没有任何两个进程同时进入临界区。但是如果有一个进程带锁休眠(lock后调用sleep(1))。则它有可能使得其他进程不能再获得锁。永久阻塞在lock函数上。至于为什么我也不知道。不设置PTHREAD_PROCESS_SHARED可能还有其他不预期的事发生,所以还是设置PTHREAD_PROCESS_SHARED好。

2.看到一篇博客说,pthread_mutexattr_t也需要在共享内存中

答:不需要。它就是mutex初始化时的一个指导,这个指导在哪个位置并不重要。

3. 第二点,不初始化那片内存为全0可以吗?

答:不可以。pthread_mutex_init有个规定,那就是它init的那片内存为全0。

参考代码

#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>  //open
#include<sys/mman.h>
#include<string.h>
int id;
int main()
{
    int fd=open("test_shared_lock_a",O_RDWR|O_CREAT,0777);
    int result=ftruncate(fd,sizeof(pthread_mutex_t)+sizeof(pthread_mutexattr_t)+sizeof(int)*40);
    pthread_mutex_t *mutex=(pthread_mutex_t *)mmap(NULL,sizeof(pthread_mutex_t)+sizeof(pthread_mutexattr_t)+sizeof(int)*40,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    memset(mutex,0,sizeof(pthread_mutex_t)+sizeof(pthread_mutexattr_t)+sizeof(int)*40);
    int* num=(int*)((char*)mutex+sizeof(pthread_mutex_t)+sizeof(pthread_mutexattr_t));
    for(int i=0;i<40;i++)
    {
        num[i]=0;
    }
   pthread_mutexattr_t* attr=NULL;

   /* 下面三行,把pthread_mutexattr_t放在了共享内存中。*/
    // attr=(pthread_mutexattr_t*)((char*)mutex+sizeof(pthread_mutex_t));
    // pthread_mutexattr_init(attr);
    // pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);


     /* 下面四行,pthread_mutexattr_t没有放在共享内存中。*/
    pthread_mutexattr_t s;
    attr=&s;
    pthread_mutexattr_init(attr);
    pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);

	// 上面7行如果都注释,则为不使用attr初始化mutex。
    pthread_mutex_init(mutex,attr);
	//创建39个子进程。并且每个进程获得一个id。
    for(int i=0;i<39;i++)
    {
        id=i+1;
        int pid=fork();
        if(pid==0)
        {
            break;
        }
        else
        {
            if(id==39)
            {
                id=0;
            }
        }
    }
    //每个进程报告自己的pid。
    printf("%d report!\n",getpid());
    //if(id!=0)
    {
        //开始检测是否有多个进程同时进入临界区。
        int j=1;
        while(j-->0)
        {
            printf("%d try to lock!\n",getpid());
            pthread_mutex_lock(mutex);
            printf("%d get lock\n",getpid());
            //拿到锁后,在对应位置做标记,表示自己进入临界区。
            num[id]=1;
            int sum=0;
            for(int i=0;i<40;i++)
            {
            sum+=num[i];
            }
            if(sum>1)
            {
                printf("%d lock_failed!\n",getpid()); //如果有两个进程同时进入临界区,sum必定大于0。
            }
            else
            {
                printf("%d test_ok\n",getpid());  //如果sum为1,说明只有一个进程进入临界区。
            }
            num[id]=0;
            sleep(1);
            pthread_mutex_unlock(mutex);
        }
    }
    
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
pthread_mutex_init函数用于初始化互斥,其参数说明如下: 1. mutex:指向要初始化的互斥变量的指针。 2. attr:指向互斥属性结构体的指针,可以为NULL,表示使用默认属性。 3. 返回值:成功返回0,失败返回错误码。 互斥属性结构体pthread_mutexattr_t的成员变量如下: 1. pshared:用于指定互斥共享属性,取值可以为PTHREAD_PROCESS_PRIVATE或PTHREAD_PROCESS_SHARED,表示互斥只能被本进程内的线程使用或者可以被多个进程的线程共享,默认为PTHREAD_PROCESS_PRIVATE。 2. type:用于指定互斥的类型,取值可以为PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE或者PTHREAD_MUTEX_DEFAULT,默认为PTHREAD_MUTEX_DEFAULT。其中,PTHREAD_MUTEX_NORMAL表示普通的互斥,不支持递归调用;PTHREAD_MUTEX_ERRORCHECK表示检错型互斥,检查互斥的状态,防止重复加;PTHREAD_MUTEX_RECURSIVE表示递归互斥,支持递归调用;PTHREAD_MUTEX_DEFAULT表示与PTHREAD_MUTEX_NORMAL相同。 3. protocol:用于指定互斥的协议,取值可以为PTHREAD_PRIO_NONE、PTHREAD_PRIO_INHERIT或者PTHREAD_PRIO_PROTECT,默认为PTHREAD_PRIO_NONE。其中,PTHREAD_PRIO_NONE表示不使用优先级继承或者保护,PTHREAD_PRIO_INHERIT表示使用优先级继承,PTHREAD_PRIO_PROTECT表示使用优先级保护。 4. process-shared:用于指定在进程间共享互斥时,互斥的属性,取值可以为PTHREAD_PROCESS_PRIVATE或PTHREAD_PROCESS_SHARED,默认为PTHREAD_PROCESS_PRIVATE。其中,PTHREAD_PROCESS_PRIVATE表示互斥不能在进程间共享,PTHREAD_PROCESS_SHARED表示互斥可以在进程间共享
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值