linux下用信号量同步线程

linux下利用信号量同步线程实现线程访问计数功能

这里是核心代码,其他参考IPC一个综合小实践

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ipc_sem.h"
#include "ipc_shm.h"
#include <pthread.h>

int g_key = 0x1234;

int doServeice()
{
    //开始使用信号量来创造临界区
    int semid = 0;
    sem_open(g_key, &semid);

     sem_p(semid); //临界区开始
        int shmhdl = 0;
        int ret = shm_creat(".", 0, &shmhdl);
        if(ret!=0)
        {
            return ret;
        }
        int *addr = NULL;
        ret =shm_map(shmhdl, (void **)&addr);
        if(ret!=0)
        {
            return ret;
        }
        // 进程访问数+1
        *((int *)addr) += 1;
        //统计总共访问的次数。
        int ncount = *((int *)addr);
        printf("ncount: %d\n", ncount);
        ret =shm_unmap(addr);
        //sleep(1);
    sem_v(semid);  //临界区开始
}

void* thread_routine(void *arg)
{
    int loop = *((int *)arg);
    for(int i=0; i<loop; ++i)
    {
        doServeice();
    }
    
    pthread_exit(NULL);
}

int main()
{
    int procnum;
    printf("输入创建子线程的个数 : \n");
    scanf("%d", &procnum);
    
    int loopnum;
    printf("输入每个子线程测试多少圈 :\n");
    scanf("%d", &loopnum);
    
    //共享内存创建
    int shmhdl = 0;
    int ret = shm_creat(".", sizeof(int), &shmhdl);
    if (ret != 0)
    {
        printf("shm_creat() Err.\n");
        return ret;
    }
    //共享内存创建成功
    
    //信号量的创建
     int  semid = 0;
    ret = sem_creat(g_key, &semid);
    if (ret != 0)
    {
        printf("sem_creat() Err. Try Again.\n");
        if (errno == EEXIST)
        {
            ret = sem_open(g_key, &semid);
            if (ret != 0)
            {
                printf("Failed Again!\n");
                return ret;
            }
        }
        else
        {
            return ret;
        }
    }
    
    int  val = 0;
    ret = sem_getval(semid, &val);
    if (ret != 0 )
    {
        printf("sem_getval() Err.\n");
        return ret;
    }
    printf("sem val: %d\n", val);
    
    //用来阻塞到键盘
    getchar();

    pthread_t tidArray[1024*4];
    for (int i=0; i<procnum; i++) 
    {
        pthread_create(&tidArray[i], NULL, thread_routine, (void*)&loopnum);
    }
    
    for (int i=0; i<procnum; i++)
    {
        pthread_join(tidArray[i],NULL);
    }
    
    shm_delete(shmhdl);
    sem_delete(g_key);

    return 0;
}

 线程同步可以使用互斥锁,也可以使用信号量。互斥锁是一个线程锁,只能锁线程不能锁进程,信号量既可以同步线程也可以同步进程。线程锁是定义在进程 之上的。

线程锁是线程库提供的一个机制,和信号量不同,信号量是IPC机制,直接归内核管理。它们两个级别不一样。

下面用线程锁同步线程功能 只要将PV操作换成线程锁的形式就可以了。

int doServeice()
{
    //开始使用信号量来创造临界区
    int semid = 0;
    sem_open(g_key, &semid);

    pthread_mutex_lock(&mutex);
     //sem_p(semid); //临界区开始
        int shmhdl = 0;
        int ret = shm_creat(".", 0, &shmhdl);
        if(ret!=0)
        {
            return ret;
        }
        int *addr = NULL;
        ret =shm_map(shmhdl, (void **)&addr);
        if(ret!=0)
        {
            return ret;
        }
        // 进程访问数+1
        *((int *)addr) += 1;
        //统计总共访问的次数。
        int ncount = *((int *)addr);
        printf("ncount: %d\n", ncount);
        ret =shm_unmap(addr);
        //sleep(1);
    //sem_v(semid);  //临界区开始
    pthread_mutex_unlock(&mutex);
}

就可以很容易的实现上面的功能。

猜你喜欢

转载自www.cnblogs.com/randyniu/p/9189814.html