首页 > 解决方案 > 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 条件),客户端彼此相邻运行,客户端写入一些数字,如果他是最后一个服务器可以处理他发出信号(完全条件)并且服务器切换到下一个。我希望你不会在运行它时遇到任何问题(正如我所写的那样)。

什么不起作用

我将不胜感激任何帮助:)

标签: cmultithreadingmutex

解决方案


有一场比赛。running_servers被同时访问且不受保护。


推荐阅读