免费注册 查看新帖 |

Chinaunix

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

几点关于线程中的互斥量/信号的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-08-29 23:28 |只看该作者 |倒序浏览
在我的第一个linux下多线程代码中,有一个主线程5个同样级别的子线程,当这个程序收到外部的SIGINT信号时,我想让主线程捕捉到该信号,并且向5个子线程发送消息告知它们保存现有工作并结束退出,此时主线程进入等待子线程结束状态.这5个子线程收到该消息后暂停现有工作并保存退出,当最后一个线程退出前,告诉主线程所有子线程均已退出.主线程被唤醒,处理结束工作并且退出.现有几点疑问:
1.主线程如何向5个子线程发送消息,如果是用pthread_kill()函数,那子线程不是要一直轮询等待该消息的到来?如果是用signal()给线程安装信号处理函数,我试过好像是所有的线程共享一个signal handler,这样的话当消息到来,不是所有的线程都会被中断(所谓的"惊群"现象?)?
2.是不是所有的signal handler都是"不可重入"的?我的意思是当线程/进程执行signal handler函数时,如果又来一个信号,会被再次中断而去执行另外一个signal handler吗?
3.整个程序中,是否只要一个mutex就可以了?假如我的代码中有两处需要互斥,这两处的代码涉及到不同的变量,需要两个互斥量保护还是一个?
4.我需要自己定义一个signal,比如叫SIGMY,怎么定义怎么操作呢?

初次尝试linux多线程编程,望多指点.

以下是我的代码:
struct dsConf
{
        int nMaxThread;
        int iSyncPort;
        int iSendPort;
        char sDBHost[20];
        char sDBName[20];
        char sDBUser[10];
        char sDBPwd[15];
};

typedef tid pthread_t;
typedef SOCKET int;
struct spth
{
        tid id;
        SOCKET soClient;
        int status;  // -1:exited  0:idle  1:processing  2:done and wait recyle
};

#define PSIGOVER 200
#define PSIGCANCEL 201

void* ThreadMain(void *arg);
tid MakeThread(struct spth *arg);
void GetConfig();
/**********signal handler*********/
void sigINT(int sig);
void sigOVER(int sig);
void sigCANCEL(int sig);
/*************global vars***************/
struct dsConf dsc;                        //config structure
tid iMainThread;                        //main thread id
pthread_mutex_t mutexCli;
pthread_cond_t condCli;
pthread_mutex_t mutexINT;
pthread_cond_t condINT;
struct spth *ppth;                        //structure stores threads info
int iPthExit;


int main(int argc,char** argv)
{
        int i;
       
       
        int nClient;                //current clients being handled

        SOCKET solisten;                //listen socket
        SOCKET socli;                        //incoming client socket
        socklen_t soclilen;
        struct sockaddr_in cliaddr, svraddr;
        /********Make usage format*********/
       
        /********Init the varibals*********/
        ppth = (struct spth*)calloc(ddc.nMaxThread,sizeof(struct spth));
        bzero(ppth,ddc.nMaxThread*sizeof(struct spth));
        nClient = 0;
        iPthExit = 0;
        iMainThread = pthread_self();;
        pthread_mutex_init (&mutexCli, NULL);
        pthread_cond_init (&condCli, NULL);
        pthread_mutex_init (&mutexINT, NULL);
        pthread_cond_init (&condINT, NULL);
         GetConfig();
        /********Create threads to handle clients*********/
        for(i=0;i<dsc.nMaxThread;i++)
                ppth.id = MakeThread( &(ppth) );                //pre-create thread spool and record the thread id into ppth
        /********Install signal handler*********/
        Signal(SIGINT, sigINT);
        Signal(PSIGOVER, sigOVER);
        /********Listen and accept clients*********/
        solisten = Socket (AF_INET, SOCK_STREAM, 0);
        bzero(&svraddr, sizeof(svraddr));
        svraddr.sin_family = AF_INET;
        svraddr.sin_addr.s_addr = htonl (INADDR_ANY);
        svraddr.sin_port = htons (dsc.iSyncPort);
        Bind(solisten, (struct sockaddr*)&svraddr, sizeof(svraddr));
        Listen(solisten, BACKLOG);
        while(1)
        {
                //get a incoming client
                soclilen = sizeof(cliaddr);
                socli = Accept(solisten, (struct sockaddr*)&cliaddr, &soclilen);
                //select an idle thread to handle it
                if(nClient == dsc.nMaxThread)
                        //too many clients right now!
                else
                {
                        for(i=0;i<dsc.nMaxThread;i++)
                        {
                                if(ppth.status == 1)
                                        break;                //so ppth is the selected thread
                        }
                }
                pthread_mutex_lock(&mutexCli);
                ppth.soClient = socli;
                ppth.status = 1;
                nClient++;
                pthread_cond_broadcast(&condCli);
                pthread_mutex_unlock(&mutexCli);
        }
}

void* ThreadMain(void *arg)
{
        struct spth *pth;
        SOCKET soConn;

        pth = (struct spth*)arg;

        pthread_detach(pthread_self());
        Signal(PSIGCANCEL,sigCANCEL);

        while(1)
        {
                pthread_mutex_lock (&mutexCli);
                while(pth->;status == 0)
                        pthread_cond_wait(&condCli, &mutexCli);
                pthread_mutex_unlock(&mutexCli);
                soConn = pth->;soClient;
                //do with socket soConn
                //...
                pthread_mutex_lock (&mutexCli);
                pth->;status = 2;
                pthread_mutex_unlock(&mutexCli);

                pthread_kill(iMainThread,PSIGOVER);
        }
        return NULL;
}

tid MakeThread(struct spth *arg)
{
        tid iNewtid;
        Pthread_create(&iNewtid, NULL, &ThreadMain,(void*)arg);
        return iNewTid;
}

void sigINT(int sig)
{
        int i;
        for(i=0;i<dsc.nMaxThread;i++)
                pthread_kill(ppth.id, PSIGCANCEL);
        pthread_mutex_lock (&mutexINT);
        while(nClient >; 0)
                pthread_cond_wait(&condINT, &mutexINT);
        pthread_mutex_unlock(&mutexINT);
        exit(0);
}

void sigOVER(int sig)
{
        int i;

        pthread_mutex_lock(&mutexCli);
        for(i=0;i<dsc.nMaxThread;i++)
        {
                if(ppth.status == 2)                //cleanup the thread
                {
                        Close(ppth.soClient,CLOSE_ALL);
                        ppth.soClient = 0;
                        ppth.status = 0;
                }
        }
        nClient--;
        pthread_mutex_unlock(&mutexCli);
        return;
}

void sigCANCEL(int sig)
{
        int i;
        //each thread finish or save its current job and exit
        //...
        pthread_mutex_lock(&mutexINT);
        for(i=0;i<dsc.nMaxThread;i++)
        {
                if(ppth.id == pthread_self())
                        if(ppth.status >; 0)
                        {
                                Close(ppth.soClient,CLOSE_ALL);
                                ppth.status = -1;
                                nClient--;
                        }
        }
        if(nClient == 0)
                pthread_cond_signal(&condINT);
        pthread_mutex_unlock(&mutexINT);
        pthread_exit(NULL);
}

论坛徽章:
0
2 [报告]
发表于 2004-08-30 00:29 |只看该作者

几点关于线程中的互斥量/信号的疑问

线程间的通信可以用管道或者POSIX信号量来解决.对于POSIX多线程程序,应该尽量避免使用信号进行通信.

实际上,实现POSIX线程库对内核是要提出改进要求的,事实上,在Linux系统下很多原来对于进程的原语已经是针对线程的了,因为Linux内核对于线程与进程的实现是一致的.基本上,你可以找一本POSIX线程的介绍看看,我也不太熟悉线程.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP