C 中的多线程服务器(线程丢失)
Multithreaded server in C (threads loss)
我正在努力解决我的多线程服务器的这个问题。服务器必须为每个连接创建一个新线程,代码如下:
int main() {
int client, val = 1;
struct sockaddr_in saddr;
socklen_t slen = sizeof(struct sockaddr_in);
s_sock = socket(F_INET, SOCK_STREAM, 0);
memset( &saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
inet_aton(HOST, &saddr.sin_addr);
setsockopt( s_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int) );
bind(s_sock, (struct sockaddr*) &saddr, sizeof(saddr));
listen(s_sock, MAX_CONN);
while(1) {
pthread_t thread;
client = accept( s_sock, (struct sockaddr*) &saddr, &slen);
printf("Accepted a client\n");
pthread_create(&thread, NULL, server, (void*) &client);
}
return 0;
}
问题是,如果我同时启动多个客户端,第一个丢失,最后一个成功完成。我猜这是因为变量 thread
在接受另一个连接时被重写。
为什么会发生这种情况以及如何解决?
这是因为 client
被重写了,而不是 thread
。
while(1) {
pthread_t thread;
client = accept( s_sock, (struct sockaddr*) &saddr, &slen);
printf("Accepted a client\n");
pthread_create(&thread, NULL, server, (void*) &client);
}
你这里有一个竞争条件。在调用 pthread_create
之后,该线程将循环返回并更改 client
的值,而无需同步。那么新创建的线程可以用 &client
做什么呢?它不能跟随指针获取描述符,因为这个线程即将在某个不可预知的时间修改client
。
想象一下,如果此循环 运行 快速循环两次,任何其他线程都没有机会 运行。您现在已经创建了两个线程并向它们传递了 &client
—— 完全相同的值。您现在有两个线程在同一个套接字上工作,一个套接字丢失了。
不要将您要更改其值的某个变量的地址传递给线程!
我正在努力解决我的多线程服务器的这个问题。服务器必须为每个连接创建一个新线程,代码如下:
int main() {
int client, val = 1;
struct sockaddr_in saddr;
socklen_t slen = sizeof(struct sockaddr_in);
s_sock = socket(F_INET, SOCK_STREAM, 0);
memset( &saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
inet_aton(HOST, &saddr.sin_addr);
setsockopt( s_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int) );
bind(s_sock, (struct sockaddr*) &saddr, sizeof(saddr));
listen(s_sock, MAX_CONN);
while(1) {
pthread_t thread;
client = accept( s_sock, (struct sockaddr*) &saddr, &slen);
printf("Accepted a client\n");
pthread_create(&thread, NULL, server, (void*) &client);
}
return 0;
}
问题是,如果我同时启动多个客户端,第一个丢失,最后一个成功完成。我猜这是因为变量 thread
在接受另一个连接时被重写。
为什么会发生这种情况以及如何解决?
这是因为 client
被重写了,而不是 thread
。
while(1) {
pthread_t thread;
client = accept( s_sock, (struct sockaddr*) &saddr, &slen);
printf("Accepted a client\n");
pthread_create(&thread, NULL, server, (void*) &client);
}
你这里有一个竞争条件。在调用 pthread_create
之后,该线程将循环返回并更改 client
的值,而无需同步。那么新创建的线程可以用 &client
做什么呢?它不能跟随指针获取描述符,因为这个线程即将在某个不可预知的时间修改client
。
想象一下,如果此循环 运行 快速循环两次,任何其他线程都没有机会 运行。您现在已经创建了两个线程并向它们传递了 &client
—— 完全相同的值。您现在有两个线程在同一个套接字上工作,一个套接字丢失了。
不要将您要更改其值的某个变量的地址传递给线程!