接下来看两个程序,是对于线程参数传递问题。
第一种传参方式:
/*
* =====================================================================================
*
* Filename: thread1.c
*
* Description: 线程参数传递
*
* Version: 1.0
* Created: 2014年07月20日 17时17分57秒
* Revision: none
* Compiler: gcc
* CopyRight: open , free , share
* Author: yexingkong(zhangbaoqing)
* Email: abqyexingkong@gmail.com
* Company: Xi'an University of post and Telecommunications
*
* =====================================================================================
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 1234 /*端口定义*/
#define BACKLOG 15 /*监听队列大小*/
struct ARG{
int connfd;
int other;
};
/* -------------------------------------------------------------------*/
/**
* @Synopsis= 线程函数
*
* @Param= arg 从主线程传递给线程函数的参数
*
* @Returns=
*/
/* ----------------------------------------------------------------------------*/
void *funtion(void *arg)
{
struct ARG info;
info.connfd = ((struct ARG *)arg) -> connfd;
info.other = ((struct ARG *)arg) -> other;
printf("test");
close(info.connfd);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
struct ARG arg; //多个线程共享此变量
int connfd,sockfd;
pthread_t tid;
.......
while(1)
{
if ((connfd = accept(sockfd,NULL,NULL)) == -1)
{
//handle excepton
}
arg.connfd = connfd;
if(pthread_create(&tid,NULL,funtion,(void *)&arg) != 0) //将共享变量arg传递给多个线程
{
//handle exception
}
}
return EXIT_SUCCESS;
}
第二种传参方式:
/*
* =====================================================================================
*
* Filename: thread1.c
*
* Description: 线程参数传递
*
* Version: 1.0
* Created: 2014年07月20日 17时17分57秒
* Revision: none
* Compiler: gcc
* CopyRight: open , free , share
* Author: yexingkong(zhangbaoqing)
* Email: abqyexingkong@gmail.com
* Company: Xi'an University of post and Telecommunications
*
* =====================================================================================
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 1234 /*端口定义*/
#define BACKLOG 15 /*监听队列大小*/
struct ARG{
int connfd;
int other;
};
/* -------------------------------------------------------------------*/
/**
* @Synopsis= 线程函数
*
* @Param= arg 从主线程传递给线程函数的参数
*
* @Returns=
*/
/* ----------------------------------------------------------------------------*/
void *funtion(void *arg)
{
struct ARG info;
info.connfd = ((struct ARG *)arg) -> connfd;
info.other = ((struct ARG *)arg) -> other;
printf("test");
close(info.connfd);
free(arg);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
struct ARG *arg; // 注意和上移程序的不同之处
int connfd,sockfd;
pthread_t tid;
//此处自行添加服务器或客户端的tcp/upd链接
.......
while(1)
{
if ((connfd = accept(sockfd,NULL,NULL)) == -1)
{
//handle excepton
}
//注意此处和前一个程序的不同之处
arg = (struct ARG *)malloc(sizeof(struct ARG));
arg -> connfd = connfd;
if(pthread_create(&tid,NULL,funtion,(void *)&arg) != 0) //将共享变量arg传递给多个线程
{
//handle exception
}
}
return EXIT_SUCCESS;
}
这两种传参方式的不同之处就在于,在第一种方式中,arg变量是所有线程共用的,而且给线程函数传递参数时,传递的是共享变量的地址,所以就有可能发生,再有多个客户链接请求时,线程A在处理客户A的请求时,执行了线程函数,而同时线程B也在处理客户B请求,那么线程A将修改arg中的内容,这时,线程B再从arg中获得的信息实际上是客户A的信息。这样就会导致arg中的值出现紊乱。
那又有什么办法避免这种冲突呢?可以通过为arg分配空间来解决这个问题,首先为每个新线程分配存储arg的空间,再将arg传递给新线程,新线程使用后释放分配的arg空间,也就是第二种传参方式,在有一个客户端链接后就为arg创建创建独立的空间,这样每个线程就有一个属于他们自己的arg空间,这样就不会共享arg空间,也就不会造成错乱。