【问题标题】:c - creating threads & joining them in a for loopc - 创建线程并将它们加入一个 for 循环
【发布时间】:2020-03-18 15:30:10
【问题描述】:

所以基本上我在 c 中为进出手机信号塔区域的车辆制作了一个模拟器。我正在尝试在simulator.c 中添加代码,使该函数为每个蜂窝塔生成一个新线程以及一个处理显示的线程。模拟器程序应该继续运行,直到所有 7 个基站线程都完成,并且基站线程应该继续,直到它们收到关闭请求。显示线程无限期地运行,但在模拟器进程完成时被终止。我无法理解我应该使用哪些参数来创建和加入线程。我在下面发布了我目前在simulator.c 程序中的内容。我的尝试是尝试循环语句为 7 个蜂窝塔创建 7 个线程。我不确定我的 pthread_create 的第一个参数是否正确,我也不确定我的第四个参数应该是什么。我知道我应该提出某种论点,但我不确定是什么。此外,我不太确定“手机信号塔线程应该继续直到它们收到关闭请求”的要求意味着什么。每个基站线程都应该从 cellTower.c 调用 handleIncomingRequests(),而显示线程应该从 display.c 调用 showSimulation()

任何帮助将不胜感激。我在网上观看了一些关于 c 线程的视频,但我仍然对它们的工作方式感到有些困惑。我在我认为仅与此问题相关的文件下方发布了,但如果有人希望我发布整个程序的每个文件,我不介意。

模拟器.c:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "simulator.h"

#include "display.c"
#include "cellTower.c"

int main() {
  City     ottawa;

  // Cell tower data
  short    xLocations[7] = {100, 400, 650, 640, 400, 120, 200};
  short    yLocations[7] = {100, 200, 150, 450, 500, 350, 500};
  short     cellRadii[7] = {110, 200, 150, 180, 160, 120, 100};
  int      cellColors[7] = {0xFF8822 /*Orange*/, 0xFF2222 /*Red*/, 0xFFFF44 /*Yellow*/,
                0x22FF22 /*Green*/, 0xAA66FF /*Purple*/, 0x0099FF /*Blue*/,
                0x999999 /*LightGray*/};

  // Set up the Cell Towers with the above data ... and no connected vehicles to begin
  ottawa.numTowers = 7;
  for (int i=0; i<ottawa.numTowers; i++) {
    ottawa.towers[i].online = 1;
    ottawa.towers[i].id = (unsigned char)i;
    ottawa.towers[i].x = xLocations[i];
    ottawa.towers[i].y = yLocations[i];
    ottawa.towers[i].radius = cellRadii[i];
    ottawa.towers[i].color = cellColors[i];
    ottawa.towers[i].numConnectedVehicles = 0;
    for (int j=0; j<MAX_CONNECTIONS; j++)
      ottawa.towers[i].connectedVehicles[j].connected = 0;
  }

  // Remove the line of code below.  Add code to spawn the necessary threads and
  // wait for their completion before exiting gracefully with some kind of message
    pthread_t cellTowers[ottawa.numTowers];
    int i;
    for(i = 0; i < ottawa.numTowers; i++){
        pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
        pthread_join(cellTowers[i], NULL);
    }

    pthread_t displayTower;
    pthread_create(&displayTower, NULL, showSimulation, "");



}

模拟器.h:

#define VEHICLE_SPEED           3   // Forward pixels per movement
#define VEHICLE_TURN_ANGLE      5   // degrees to turn for each vehicle movement

#define NUM_TOWERS              7   // Number of cell towers within the city borders

#define SERVER_IP     "127.0.0.1"   // IP address of simulator server
#define SERVER_PORT          6000   // PORT of the simulator server

// Command codes sent from client to server
#define SHUTDOWN           1
#define CONNECT            2
#define UPDATE             3

// Command codes sent from server to client
#define YES                5
#define NO                 6
#define NOT_OK_BOUNDARY    7
#define NOT_OK_COLLIDE     8


typedef struct {
  int   x;
  int   y;
  int   direction;
  char  towerID;
} Vehicle;

typedef struct {
  int   x;
  int   y;
  char  connected;
} ConnectedVehicle;


typedef struct {
  char               online; // 0 = no, 1 = yes
  char               id;
  short              x;
  short              y;
  short              radius;
  int                color;
  ConnectedVehicle   connectedVehicles[MAX_CONNECTIONS];
  short              numConnectedVehicles;
} CellTower;

typedef struct {
  CellTower towers[NUM_TOWERS];
  short     numTowers;
} City;

cellTower.c:

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>


void *handleIncomingRequests(void *ct) {
  CellTower       *tower = ct;
}

display.c:

#include <unistd.h>
#include <X11/Xlib.h>

//Display-related variables
Display *display;
Window   win;
GC       gc;


// Initialize and open the simulator window with size CITY_WIDTH x CITY_HEIGHT.
void initializeWindow() {
  // Open connection to X server
  display = XOpenDisplay(NULL);

  // Create a simple window, set the title and get the graphics context then
  // make is visible and get ready to draw
  win = XCreateSimpleWindow(display,  RootWindow(display, 0), 0, 0,
                CITY_WIDTH, CITY_HEIGHT, 0, 0x000000, 0xFFFFFF);
  XStoreName(display, win, "Vehicle Simulator");
  gc = XCreateGC(display, win, 0, NULL);
  XMapWindow(display, win);
  XFlush(display);
  usleep(20000);  // sleep for 20 milliseconds.
}

// Close the display window
void closeWindow() {
  XFreeGC(display, gc);
  XUnmapWindow(display, win);
  XDestroyWindow(display, win);
  XCloseDisplay(display);
}


// Redraw all the cell towers and all the vehicles that are connected to towers.
// This code should run in an infinite loop continuously drawing the city.
// Vehicles are drawn as circles with radius VEHICLE_RADIUS.
void *showSimulation(void *c) {
  City  *city = c;

  // Open the window
  initializeWindow();

  // Now keep redrawing until someone kills the thread
  while(1) {
    // Erase the background 
    XSetForeground(display, gc, 0xFFFFFF);
    XFillRectangle(display, win, gc, 0, 0, CITY_WIDTH, CITY_HEIGHT);

    // Draw all the cell towers
    for (int i=0; i<city->numTowers; i++) {
      short r = city->towers[i].radius;
      XSetForeground(display, gc, city->towers[i].color);
      for (int b=-3;b<=3; b++)
    XDrawArc(display, win, gc,
         city->towers[i].x-r+b, city->towers[i].y-r+b,
         2*(r-b), 2*(r-b), 0, 360*64);
    }

    // Draw all the vehicles within each cell tower's range 
    for (int t=0; t<city->numTowers; t++) {
      for (int i=0; i<MAX_CONNECTIONS; i++) {
    if (city->towers[t].connectedVehicles[i].connected) {
      XSetForeground(display, gc, city->towers[t].color);
      XFillArc(display, win, gc,
           city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
           city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
           2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
      XSetForeground(display, gc, 0x000000); // draw a black border
      XDrawArc(display, win, gc,
           city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
           city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
           2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
    }
      }
    }
    XFlush(display);
    usleep(2000);
  }

  closeWindow();
  pthread_exit(NULL);
}

另外,如果有人有一些有用的线程资源,那也将不胜感激!!!

【问题讨论】:

  • 创建一个线程并立即加入它完全违背了使用线程的意义。

标签: c multithreading for-loop pthreads


【解决方案1】:

这里有几个问题:

pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
    pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
    pthread_join(cellTowers[i], NULL);
}
  1. pthread_create 存储它在由第一个参数指向的内存位置创建的线程ID。 因此,第一个参数应该是&amp;cellTowers[i](或等价的cellTowers + i),而不是你传递的cellTowers[i]。

    你的编译器应该警告你你传入了一个错误类型的值。如果您尚未打开编译器警告,请现在打开。对于 GCC,请使用 -Wall -Wextra -Werror。

  2. 只要你观察到这个序列:

    pthread_create ...
    pthread_join ...

    在两者中使用相同的线程 ID,您可以立即知道程序已损坏。 pthread_join 将等待线程完成。因此,在第一个线程退出之前不会创建额外的线程。

    大多数线程程序的工作方式:

    for (...) pthread_create... // create all worker threads
    // possibly perform additional work in main thread
    for (...) pthread_join... // wait for all threads to finish

  3. 最后,回答你的问题:第四个参数应该是什么?

    由于handleIncomingRequests() 期望参数是指向CellTower 的指针,所以第4 个参数应该是(该参数直接 传递给您的函数)。

    在这个程序中,第四个参数应该是&amp;ottawa.towers[i](或等效的ottawa.towers + i)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    相关资源
    最近更新 更多