具有多个线程的程序,不打印预期输出

Program with multiple threads, not printing expected output

本文关键字:打印 输出 程序 线程      更新时间:2023-10-16

我使用的是Ubuntu 12,当我在终端上编译代码时,我使用:$ g++ -o ./myProgram ./main.cpp,则$ ./myProgram我没有收到任何错误或警告,但它不会打印主功能之外的任何内容。

由于某种原因,主函数中的pthread_creat命令似乎不起作用。

这是我的程序代码:

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
using namespace std;
pthread_mutex_t jobMutex;
key_t key = 5678;
#define SHMSZ 27
int shmid;
class Job {
public:
int speed, pleasant, easy;
//initialization, constructor, destructor
Job() {
}
Job(int new_s, int new_p, int new_e) {
    speed = new_s;
    pleasant = new_p;
    easy = new_e;
}
~Job() {
}
};
struct sh_data {
Job j_list[10]; //array of jobs on bulletin board
int clock;
int kid_count;
} *shared, *update;
class Child {
private:
int pid;
int j_pref;
Job* j_list;
int clock;
int score;
public:
Child() {
} //constructor
void read_mem() {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    j_list = data->j_list;
    clock = data->clock;
    pthread_mutex_unlock(&jobMutex);
}
void write_mem(int index) {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    data->j_list[index].speed = 0;
    pthread_mutex_unlock(&jobMutex);
}
//all preference functions
void pref_quick() {
    cout << "Child prefers a quick job n";
    read_mem();
    while (clock < 20) {
        pthread_mutex_lock(&jobMutex);
        read_mem();
        int cur_job;
        int speed = j_list[0].speed;
        for (int i = 0; i < 10; i++) {
            if (j_list[i].speed < speed && j_list[i].speed > 0) {
                cur_job = i;
                speed = j_list[i].speed;
            }
        }
        cout << "Child " << pid << " selected job " << cur_job << " with speed " << speed << "n";
        //calculate total score so far
        score += j_list[cur_job].speed + j_list[cur_job].pleasant + j_list[cur_job].easy;
        write_mem(cur_job);
        pthread_mutex_unlock(&jobMutex);
        sleep(j_list[cur_job].speed);
    }
}
void pref_profit() {
    cout << "Child prefers a job with highest profit n";
    read_mem();
    while (clock < 20) {
        pthread_mutex_lock(&jobMutex);
        read_mem();
        int cur_job;
        int profit = 0;
        for (int i = 0; i < 10; i++) {
            if (j_list[i].speed + j_list[i].pleasant + j_list[i].easy > profit) {
                cur_job = i;
                profit = j_list[i].speed + j_list[i].pleasant + j_list[i].easy;
            }
        }
        cout << "Child " << pid << " selected job " << cur_job << " with profit " << profit << "n";
        //calculate total score so far
        score += profit;
        write_mem(cur_job);
        pthread_mutex_unlock(&jobMutex);
        sleep(j_list[cur_job].speed);
    }
}
void pref_simple() {
    cout << "Child prefers a simple job n";
    read_mem();
    while (clock < 20) {
        pthread_mutex_lock(&jobMutex);
        read_mem();
        int cur_job;
        int ease = j_list[0].easy;
        for (int i = 0; i < 10; i++) {
            if (j_list[i].easy < ease) {
                cur_job = i;
                ease = j_list[i].easy;
            }
        }
        cout << "Child " << pid << " selected job " << cur_job << " with ease " << ease << "n";
        //calculate total score so far
        score += j_list[cur_job].speed + j_list[cur_job].pleasant + j_list[cur_job].easy;
        write_mem(cur_job);
        pthread_mutex_unlock(&jobMutex);
        sleep(j_list[cur_job].speed);
    }
}
void pref_clean() {
    cout << "Child prefers a clean job n";
    read_mem();
    while (clock < 20) {
        pthread_mutex_lock(&jobMutex);
        read_mem();
        int cur_job;
        int clean = j_list[0].pleasant;
        for (int i = 0; i < 10; i++) {
            if (j_list[i].pleasant < clean) {
                cur_job = i;
                clean = j_list[i].pleasant;
            }
        }
        cout << "Child " << pid << " selected job " << cur_job << " with cleanliness " << clean << "n";
        //calculate total score so far
        score += j_list[cur_job].speed + j_list[cur_job].pleasant + j_list[cur_job].easy;
        write_mem(cur_job);
        pthread_mutex_unlock(&jobMutex);
        sleep(j_list[cur_job].speed);
    }
}
void* worker() {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    j_list = data->j_list;
    pid = data->kid_count;
    j_pref = rand() % 4;
    data->kid_count++;
    pthread_mutex_unlock(&jobMutex);
    cout << "Job Preference for Child " << pid << " is: " << j_pref << "n";
    //select a job preference
    switch (j_pref) {
        case 0: //fastest job
            cout << "Selecting quickest jobn";
            pref_quick();
            break;
        case 1: //cleanest job
            cout << "Selecting the most pleasant jobn";
            pref_clean();
            break;
        case 2: //simplest job
            cout << "Selecting the most simple jobn";
            pref_simple();
            break;
        case 3: //most profitable job
            cout << "Selecting the most profitable jobn";
            pref_profit();
            break;
        default: //quickest job by default
            cout << "Selecting quickest jobn";
            pref_quick();
            break;
    }
}
~Child() { //destructor
}
//static helper function to get rid of hidden "this" parameter from pthread_create
static void *Child_helper(void *context) {
    cout << "tChild helper function calledn";
    return ((Child *) context)->worker();
}
};
class Mom {
private:
Job j_list[10]; //unending list of 10 jobs
int clock;
pthread_t child_id[4]; //thread ids for each child
public:
//create job with random speed, pleasant, easy values
Job newJob() {
    int rand_val[3];
    for (int i = 0; i < 3; i++) {
        rand_val[i] = rand() % 5 + 1;
    }
    return Job(rand_val[0], rand_val[1], rand_val[2]);
}
void read_mem() {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < 10; i++) {
        j_list[i] = data->j_list[i];
    }
    clock = data->clock;
    pthread_mutex_unlock(&jobMutex);
}
void write_mem(Job new_job, int index, int clock) {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    data->j_list[index] = new_job;
    data->clock = clock;
    pthread_mutex_unlock(&jobMutex);
}
void write_mem(int clock) {
    sh_data* data;
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        cerr << "tshmgetn";
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&jobMutex);
    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "tshmatn";
        exit(EXIT_FAILURE);
    }
    data->clock = clock;
    pthread_mutex_unlock(&jobMutex);
}
//chores() creates shared memory, checks checks and update shared memory, and creates children
void* chores() {
    cout << "tChores function calledn";
    shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT);
    cout << "tValue of shmid: " << shmid << "n";
    if (shmid == -1) {
        shmid = shmget(key, sizeof (sh_data), IPC_CREAT);
        if (-1 == shmid) {
            cout << "tCould not get shmidn";
        } else {
            pthread_mutex_lock(&jobMutex);
            //system chooses the address
            shared = (sh_data *) shmat(shmid, 0, 0);
            update = shared;
            pthread_mutex_unlock(&jobMutex);
        }
    } else {
        pthread_mutex_lock(&jobMutex);
        cout << "Mom created job list!n";
        //system chooses the address
        shared = (sh_data *) shmat(shmid, (void*) 0, 0);
        update = shared;
        update->kid_count = 0;
        pthread_mutex_unlock(&jobMutex);
    }
    sh_data* data;
    Child * child[4];
    for (int i = 0; i < 4; i++) {
        cout << "~~Thread created for Child " << i + 1 << "n";
        child[i] = new Child();
        //calls worker function from Child class
        pthread_create(&child_id[i], NULL, &Child::Child_helper, child[i]);
    }
    while (clock < 20) {
        cout << "tMom will sleep for 2 unitsn";
        sleep(2);
        pthread_mutex_lock(&jobMutex);
        read_mem();
        for (int i = 0; i < 10; i++) {
            if (j_list[i].speed == 0) {
                cout << "Mommy added a new job to the bulletin board!!n";
                j_list[i] = newJob();
                write_mem(j_list[i], i, clock);
            }
        }
        clock += 2;
        write_mem(clock);
        pthread_mutex_unlock(&jobMutex);
        cout << "Mom says time is now: " << clock << "n";
    }
    payup();
}
void payup() {
    int max, winner;
    max = 0;
    for (int i = 0; i < 4; i++) {
        //wait for all children to finish tasks
        int* status = 0;
        pthread_join(child_id[i], (void**) status);
        cout << "Child " << i << " completes tasks that earned him/her " << *status << " points!n";
        if (max < *status) {
            max = *status;
            winner = i;
        }
    }
    cout << "The winner is child " << winner << ", with " << max << " points!n";
}
Job* get_jlist() {
    return j_list;
}
int get_time() {
    return clock;
}
//static helper function to get rid of hidden "this" parameter from pthread_create
static void *Mom_helper(void *context) {
    cout << "tHelper function calledn";
    return ((Mom *) context)->chores();
}
//initialization, constructor, destructor
Mom() {
    srand(time(NULL));
}
~Mom() {
}
};
int main() {
cout << "Program 7: Chores using Threadsnn";
pthread_t threads;
pthread_mutex_init(&jobMutex, NULL);
//instantiate mom class and call chores()
Mom* mommy = new Mom();
cout << "~~Made Momn";
//calls chores function from Mom class
pthread_create(&threads, NULL, &Mom::Mom_helper, mommy);
cout << "~~Created threadsn";
pthread_mutex_destroy(&jobMutex);
cout << "~~Destroyed threadsn";
return 0;
}

我做错了什么吗?我一直在到处寻找,并将我的代码与其他代码进行比较,结果似乎是正确的。但它不起作用。有人能解释一下这种情况吗?

这有很多代码要读,但您似乎没有在等待线程。您的主线程调用pthread_create,并且(很可能)在新线程有机会运行之前退出进程。

你可能想打电话给pthread_join,在pthread_mutex_destroy之前的某个地方。

pthread_create(&threads, ...);
pthread_join(threads, zahir);