如何在整个程序中访问有关线程的信息

How to access info about a thread throughout a program

本文关键字:线程 信息 访问 程序      更新时间:2023-10-16

问题1:我试图命名每个线程,以便它可以在整个程序中使用,但收到了错误,如"请求非类类型为pthread_t的'planes[t]'中的成员'fid'。它指的是平面[t].tid的使用或平面[t].startState的使用。我不知道如何为每个单独的线程获取/保存这些值。

问题2:一旦我有了线程的startState,我如何将线程发送到takeoff()函数(一系列开关状态和printfs)。

问题3:应该向StartState函数传递什么?我试图让每个线程记住它的开始状态,这样在代码的后面,我就可以让航班"降落"或"起飞">

以下是相关代码:更新时间:10/06 22:37

#include <pthread.h>
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <unistd.h>
#include <algorithm>
#include <time.h>
#include <ctime> 
#define NUM_THREADS 3       //3 flights
using std::queue;
using std::vector; 
pthread_mutex_t runway1lock;
pthread_mutex_t runway2lock;
bool run1occupied;
bool run2occupied;
struct flight_data{                 //each plane has these characteristics
//void *FlightID;
long fid;
int startState;        // if start=1 ==> taking off    :::     if start=2 ==> landing
int flyTime;            //fly == randomly generated time (order) of takeoff/land                
};
struct flight_data flightinfo[NUM_THREADS];
void *FlightID(void *flightid){
struct flight_data *my_flights;
my_flights = (struct flight_data*)flightid;
int taskid;
taskid = my_flights->fid;
//       long fid;
//      fid = (long)flightid;
//      printf("Flight #%1dn", tid);
pthread_exit(NULL);
}
void Start(struct flight_data my_flights){
my_flights = (struct flight_data)my_flights;
int startState;
srand(time(0));
my_flights.startState = rand() % 2+1;
std::string startstring;
if(my_flights.startState == 1){
startstring = "Taking off";
}
if(my_flights.startState == 2){
startstring = "Landing";
}
for(int i = 1; i<NUM_THREADS+1; i++){
std::cout << "Start state for Flight # " << i << " is " << startstring << std::endl;
}
}
void takeoff(struct flight_data my_flights){
my_flights = (struct flight_data)my_flights;    
for(int i = 1; i<NUM_THREADS+1; i++){
int state = my_flights.startState;
switch(state){  
case 1:{        //G (GATE)
std::cout << "Flight # " << flightinfo[i].fid << " is listed as waiting at the gate." << std::endl; 
std::cout << "Flight # " << flightinfo[i].fid << "'s position in queue for runway: " << flightinfo[i].flyTime << std::endl; 
sleep(3);
state = 2;
break;
}   
case 2: {       //Q (queue) -- sets order for use of runway
queue<pthread_t> queue;
vector<int> flightTimes;    
int soonestFlightTime = 10;
flightTimes.push_back(flightinfo[i].flyTime);           //put all flight times into a vector called flightTimes
std::sort(flightTimes.begin(), flightTimes.end());      //sort the vector of flightTimes low to high
std::reverse(flightTimes.begin(), flightTimes.end());       //flips vector -- high(front) to low(back)
while(!flightTimes.empty()){
if (flightinfo[i].flyTime == flightTimes.back()){   //if a thread has the soonest flight time   
queue.push(i);      //then put the flight in the runway queue
flightTimes.pop_back();     //pop off the soonest flight time 
}
}   
while(!queue.empty()){
if(flightinfo[i].fid == queue.front()){
state = 3;
queue.pop();
sleep(3);
}   
}
break;
}
case 3: {       //CLR (clearance for runway)
std::cout << "Flight # " << flightinfo[i].fid << " has clearance to move to the runway." << std::endl;  //will go in order of queue
if(run1occupied){
sleep(3);
}
//  else if(collide){
//      state = 7;
//  }
else{
state = 4;
}
break;      
}
case 4: {       //RTO (runway takeoff)
pthread_mutex_lock(&runway1lock);
run1occupied = true;
std::cout << "Flight # " << flightinfo[i].fid << " is taking off. Runway occupied. Stand by." << std::endl;
sleep(3);
pthread_mutex_unlock(&runway1lock);
run1occupied = false;
state = 5;
break;
}
case 5: {       //CZ (cruise)
std::cout << "Flight # " << flightinfo[i].fid << " is reaching proper altitude and cruising toward destination." << std::endl; 
sleep(3);
//  if(!collide){
state = 6;
//  }
//  else{
//      state = 7;  //collision!!!
//  }
break;
}
case 6: {       //RMV (remove from monitoring list)
std::cout << "Flight # " << flightinfo[i].fid << " has been removed from the monitoring list." << std::endl;
break; 
}       
case 7:{        //COLL (collision)
std::cout << "Collision in the air. There were many casualties." << std::endl;
break;
}
}
}
}
void landing(struct flight_data my_flights){
my_flights = (struct flight_data)my_flights;
for (int i = 0; i<NUM_THREADS; i++){
int state = my_flights.startState;
switch(state){
case 1:{        //ENTR (enter monitoring list)
state = 2;
break;
}
case 2:{        //Q (queue)
//if not the first thing in the queue then state = 4;
//otherwise state = 3;
}
case 3:{        //RWL (runway land)
state = 5;
break;
}
case 4:{        //HVR (hover)
//if first in queue then state = 3;
//otherwise stay here
//if collision state = 7;
}
case 5:{        //CLR (clearance to move to gate)
//if collision state = 7
//otherwise state = 6;
}
case 6:{        //G (gate)
}
case 7:{        //COLL (collision)
}
}
}
}
/*
bool collision(){
bool collide;
//random
if(){
collide = true;
}
else{
collide = false;
}
return collide;
}*/
int main(int argc, char *argv[]){
pthread_t flights[NUM_THREADS];         //pthread_t keeps a thread ID after the thread is created with pthread_create()
//it's like an index on a vector of threads
int *taskids[NUM_THREADS];
int rc;
long t;
for (t=1; t<=NUM_THREADS; t++){                                 //loop creates threads(flights)
printf("In main: Creating flight %1dn", t);
flightinfo[t].fid= t;
rc = pthread_create(&flights[t], NULL, FlightID, (void *)&flights[t]);
if (rc){
printf("ERROR: return code from pthread_create() is %dn", rc);
return (-1);
}
printf("Created flight %1dn", t);
//      Start(flightinfo[t]);
flightinfo[t].startState = rand() % 2+1;
std::cout << flightinfo[t].startState << std::endl;
if((flightinfo[t].startState)==1){
std::cout << "Flight # " << flightinfo[t].fid << " is listed with start state as " << flightinfo[t].startState << std::endl;
takeoff(flightinfo[t]);
//go to takeoff function and go through switch case     
}
if((flightinfo[t].startState)==2){
std::cout << "Flight # " << flightinfo[t].fid << " is listed with start state as " << flightinfo[t].startState << std::endl;
landing(flightinfo[t]);
//go to landing function and go through switch case     
}
}
pthread_exit(NULL);
}

您似乎混淆了pthread_t管理变量planes和包含飞行数据的变量flights

pthread_t管理变量planes由pthread库使用,您实际上应该只将其用作pthread函数库调用的参数,否则就别管它了,不用担心它。把变量planes想象成一个存储区域,你创建它,然后把它交给pthread库使用,这样你就把这个变量的所有权交给了pthred库。

因此,业务的第一步是分离并区分pthread管理和线程操作的实际数据。

您有几个地方正在使用pthread管理变量planes,就好像它是一个飞行数据变量一样。事实并非如此。用flights替换planes

if((flights[t].startState)==1){
std::cout << "Flight # " << flights[t].fid << " is listed as waiting at the gate." << std::endl;
void takeoff();
//go to takeoff function and go through switch case     
}
if((flights[t].startState)==2){
std::cout << "Flight # " << flights[t].fid << " is listed as waiting to land." << std::endl;
//go to landing function and go through switch case     
}

函数StartState()中的这部分源代码没有意义。

for(int i = 0; i<NUM_THREADS; i++){
startState = rand() % 1+2;
}
startState = my_flights->startState;

我想你想用一些随机的开始状态来设置一个特定航班的开始状态。因此,我希望源看起来像下面这样,因为我假设您对设置特定飞行的开始状态感兴趣,并且循环除了练习随机数生成器NUM_THREADS次之外,什么都不做,所以循环应该被下面这样的东西代替。然而,我还没有检查你对此的逻辑,以及范围是否正确。

my_flights->startState = rand() % 1+2;

建议的行动方案

您应该将线程看作是一个小程序或应用程序。对于这个简单的例子,我建议您首先编写飞行逻辑,而不必担心线程。因此,如果你从一个函数开始,比如FlyPlaneFlight (),你将一个flight变量传递给它,然后这个函数调用其他函数来做各种事情,当flight结束时,它返回给调用者,你可能会处于线程的有利位置。在为单个飞行准备好逻辑之后,您可以使用pthread库来创建多个飞行,方法是初始化飞行数据,然后创建一个使用FlyPlaneFlight()的线程。

你还需要考虑时间和互动。对于这种模拟,我怀疑您希望FlyPlaneFlight()函数具有一个循环,在该循环中对飞行数据进行更改,然后线程将休眠一两秒钟。作为一个开始测试,使用具有一定迭代次数的for循环,然后将退出,如以下所示:

for (int i = 0; i < 100; i++) {
// modify the flight data
sleep(1000);   // sleep for a second (1000 milliseconds) then repeat
}

如果这变得更加复杂,使得飞行不是独立的,而是必须以某种方式同步,那么您将需要研究pthread库的线程同步功能。

因此,当您将FlyPlaneFlight()函数封装为pthread_create()函数时,它可能看起来像以下源代码片段:

void *FlightID(void *flightdata){
struct flight_data *my_flights = (struct flight_data*)flightdata;
// initialize the flight data as needed
FlyPlaneFlight (myFlight);
// print out the myFlight data so that you can see what happened
pthread_exit(NULL);
}

其想法是将飞机飞行视为一个对象,飞行所需的所有数据都在struct flight_data结构中,在大多数情况下,您可以忽略pthread库,该库不涉及实际飞行模拟,而是用于模拟多个飞行对象。因此,您创建了多个线程,每个线程都有自己的飞行数据,然后使用相同的代码来处理飞行数据。你可以做一些随机化,这样所有不同的航班都会有不同的历史,它们会做不同的事情。

编辑

然后,你的主菜单会有一个类似以下的循环

for (t=0; t<NUM_THREADS; t++){                    //loop creates threads(flights)
std::cout << "In main: Creating flight " << t+1 << std::endl;
flights[t].fid= t+1;
rc = pthread_create(&planes[t], NULL, FlightID, (void *)&flights[t]);
if (rc){
std::cout << "ERROR: return code from pthread_create() is " << rc << std::endl;
return (-1);
}
std::cout << "Created flight " << t << std::endl;
}
pthread_exit(NULL);    // exit the main thread and allow remaining threads to complete

这将创建各种线程并让它们运行。在FlyPlaneFlight()函数的循环中,每次循环时都会打印出类似以下内容的状态,因此FlyPlaneFlight()函数看起来像这样,您可以使用一种有限状态机从一个状态移动到另一个状态,可能会使用随机数生成器,使用rand()函数掷虚拟骰子来确定下一个状态或保持当前状态:

void FlyPlaneFlight (struct flight_data *my_flights)
{
for (int i = 0; i < 100; i++) {
switch (my_flights->startState) {
case 1:
std::cout << "Flight # " << my_flights->fid << " is listed as waiting at the gate." << std::endl;
// now move the flight state to the next state.
break;
case 2:
std::cout << "Flight # " << my_flights->fid << " is listed as waiting to land." << std::endl;
// now move the flight state to the next state.
break;
// other case statements for other flight states and moving between the
// various flight states.
}
sleep (1000);  // sleep this thread for one second (1000 milliseconds) then repeat
}
}

根据2006年10月22时37分的源代码更新编辑#2

在源代码中,您有一个全局数组变量flights,您正试图通过源代码直接访问它。这是一个导致你陷入问题的错误。您需要做的是让线程create调用为特定线程分配一个特定的飞行数组元素。在这一点上,您不必担心flight数组,而是只使用分配给该线程的特定元素。

例如,使用线程创建,如下所示,它创建一个线程,并为正在创建的线程分配一个唯一的数组元素。

rc = pthread_create(&planes[t], NULL, FlightID, (void *)&flights[t]);

线程入口函数FlightID()接受指向该数组元素的指针作为自变量,因此在这一点上,对flights[t]中的飞行数据进行操作的任何函数都可以使用指向该数组元件的指针。职能部门应该只担心他们的特定航班,而不是其他人的航班。

同样,在线程启动后,函数FlightID()及其调用的任何函数都不应该再关心其他线程,因此这些函数中带有NUM_THREADS的所有循环都不应该存在。

这个想法是通过调用在特定航班上运行的FlightID()来启动一个小程序。然后,对于多个线程,每个线程从FlightID()开始。这类似于main()作为C/C++程序的入口点的想法,其中main()有一些参数,程序从main()开始。在线程的情况下,线程从线程入口函数开始,在您的情况下是FlightID()

我在FlyPlaneFlight()中有一个循环的原因是为特定飞行的有限状态机提供一系列状态更改。换言之,环路内的是一次飞机飞行。

看看我建议的线程创建循环和你的之间的区别。我的只是创建线程。您的创建线程,然后尝试使用flights数组元素执行操作,该元素现在应该属于创建的线程,而不是main。

所有这些变量似乎都存储在flights数组中,而不是planes数组中。