c - C中的线程同步:为什么它们重叠
问题描述
我有一些用 C 编写的代码,我想问你:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#define COLOR_YELLOW "\x1b[33m"
#define COLOR_RED "\x1b[31m"
#define COLOR_RESET "\x1b[0m"
int tests = 3;
int running_servers;
int servers;
int clients;
int max_clients;
int current_id = 0;
int clients_handled = 0;
void *server(void *arg);
void *client(void *arg);
pthread_mutex_t server_mutex;
pthread_mutex_t client_mutex;
pthread_cond_t order_cond;
pthread_cond_t getting_clients;
pthread_cond_t full;
int main(int argc, char *argv[]) {
if(argc != 4) { printf("expected 3 arguments"); return 1; }
// INIT
servers = atoi(argv[1]);
running_servers = atoi(argv[1]);
clients = atoi(argv[2]);
max_clients = atoi(argv[3]);
pthread_mutex_init(&server_mutex, NULL);
pthread_mutex_init(&client_mutex, NULL);
pthread_cond_init(&order_cond, NULL);
pthread_cond_init(&getting_clients, NULL);
pthread_cond_init(&full, NULL);
pthread_t *server_thread = calloc(servers, sizeof(pthread_t));
pthread_t *client_thread = calloc(clients, sizeof(pthread_t));
// CREATING CLIENT THREADS
int *arg;
for (int i = 0; i < clients; i++) {
arg = malloc(sizeof(int));
*arg = i;
if (pthread_create(&client_thread[i], NULL, client, (void *) arg))
perror("pthread_create error for passenger");
}
// CREATING SERVER THREADS
for (int i = 0; i < servers; i++) {
arg = malloc(sizeof(int));
*arg = i;
if (pthread_create(&server_thread[i], NULL, server, (void *) arg))
perror("pthread_create error for car");
}
// JOINING ENDING THREADS
for (int i = 0; i < servers; i++)
if (pthread_join(server_thread[i], NULL)) perror("pthread_join error for car");
for (int i = 0; i < clients; i++)
if (pthread_join(client_thread[i], NULL)) perror("pthread_join error for passenger");
return 0;
}
void *server(void *arg) {
int id = *(int *) arg;
printf(COLOR_RED "SERVER: %d" COLOR_RESET " start working\n", id);
while (tests--) {
// ONLY ONE SERVER CAN WORK - SERVERS ARE RUN IN ORDER
pthread_mutex_lock(&server_mutex);
while (id != current_id)
pthread_cond_wait(&order_cond, &server_mutex);
printf(COLOR_RED "SERVER: %d" COLOR_RESET " starts\n", id);
printf(COLOR_RED "SERVER: %d" COLOR_RESET " gets clients \n", id); // server gets clients
pthread_cond_broadcast(&getting_clients);
pthread_cond_wait(&full, &client_mutex); // server is waiting for signal (from any client)
printf(COLOR_RED "SERVER: %d" COLOR_RESET " is full \n", id); // that he has max number of clients
printf(COLOR_RED "SERVER: %d" COLOR_RESET " stops \n", id);
current_id = (current_id + 1) % servers;
pthread_mutex_unlock(&server_mutex);
pthread_cond_broadcast(&order_cond);
}
running_servers -= 1;
return NULL;
}
void *client(void *arg) {
int id = *(int *) arg;
printf(COLOR_YELLOW "CLIENT: %d" COLOR_RESET " starts\n", id);
while (running_servers) {
pthread_mutex_lock(&client_mutex); // only one client at the time (should be)
pthread_cond_wait(&getting_clients, &client_mutex);
printf(COLOR_YELLOW "CLIENT: %d" COLOR_RESET " has access to server %d\n", id,current_id);
clients_handled++;
for (int j = 0; j < 10; j++) { // client writes some numbers
printf("%d: ", id);
for (int i = 0; i < 10; i++) {
printf("%d ", 10 * j + i);
}
printf("\n");
}
if(clients_handled == max_clients) { // client sends signal he is the last one server can handle
printf(COLOR_YELLOW "CLIENT: %d" COLOR_RESET " server %d is full, shifting to next server\n", id, current_id);
clients_handled = 0;
pthread_cond_signal(&full);
}
pthread_mutex_unlock(&client_mutex);
}
return NULL;
}
它不漂亮,但它正在工作(有点)。
工作原理: 程序获取 3 个参数:服务器数量、客户端数量、服务器中的最大客户端数量。我们将服务器和客户端创建为线程。目前,一个客户端和一个服务器应该处于活动状态(因为互斥体 server_mutex 和 client_mutex)。服务器广播他处于活动状态的信息(getting_clients 条件),客户端彼此相邻运行,客户端写入一些数字,如果他是最后一个服务器可以处理他发出信号(完全条件)并且服务器切换到下一个。我希望你不会在运行它时遇到任何问题(正如我所写的那样)。
什么不起作用
看起来 server_mutex 完成了他的工作,服务器正在一个接一个地运行,但 client_mutex 没有,而且我不知道为什么有时客户端会重叠 - 一个客户端启动,而其他客户端尚未完成写入数字。
我对 getting_clients 的第一次广播有问题,因为由于未知原因,它有时会在某些客户端尚未创建时发送。这尤其糟糕,当我有 3 个服务器和 2 个客户端时,它们甚至可能无法启动。这对我来说很奇怪,因为首先创建了客户端线程,我想知道是否有任何解决方案(除了在创建客户端线程和服务器线程之间添加 sleep() ,但我想避免这种情况)
由于某种原因程序没有结束,它只是在一瞬间停止,这可能与以前的程序有关,但我还没有找到解决方案,
您有什么想法可以让所有客户都得到平等对待吗?我的意思是我有 3 台服务器和 100 个客户端,我不希望遇到这样的情况:很少有客户端一直在写,并且有一个组还没有访问服务器的权限
我将不胜感激任何帮助:)
解决方案
有一场比赛。running_servers
被同时访问且不受保护。
推荐阅读
- dynamics-crm - 当我没有架构实体名称时如何使用获取记录在另一个对象上查找相关记录 - 只是逻辑名称
- jquery - 点击图例动态计算百分比
- c++ - 在 Visual Studio 中从 ctypes 进行远程 DLL 调试
- azure-pipelines - Azure Data Factory send failed notifications to teams channel
- python - 4D 张量形状
- javascript - math.random 总是在数组中返回 1
- javascript - 为什么第二个 Materialise 轮播显示为灰色/不显示?
- laravel - 如何在 Laravel 的关系树中搜索所有关联?
- ios - UIPageViewController 的子视图控制器的生命周期错误
- javascript - @click 事件不会更改 Vue.js 中的数据属性