使用多个线程编程,而不是打印预期输出

时间:2012-07-10 20:54:38

标签: c++ linux pthreads shared-memory

我正在使用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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 job\n";
            pref_quick();
            break;
        case 1: //cleanest job
            cout << "Selecting the most pleasant job\n";
            pref_clean();
            break;
        case 2: //simplest job
            cout << "Selecting the most simple job\n";
            pref_simple();
            break;
        case 3: //most profitable job
            cout << "Selecting the most profitable job\n";
            pref_profit();
            break;
        default: //quickest job by default
            cout << "Selecting quickest job\n";
            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 called\n";
    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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 << "\tshmget\n";
        exit(EXIT_FAILURE);
    }

    pthread_mutex_lock(&jobMutex);

    if ((data = (sh_data *) shmat(shmid, NULL, 0)) == (sh_data *) -1) {
        cerr << "\tshmat\n";
        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 called\n";

    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 shmid\n";
        } 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 units\n";
        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 called\n";
    return ((Mom *) context)->chores();
}

//initialization, constructor, destructor

Mom() {
    srand(time(NULL));
}

~Mom() {
}
};

int main() {
cout << "Program 7: Chores using Threads\n\n";

pthread_t threads;
pthread_mutex_init(&jobMutex, NULL);

//instantiate mom class and call chores()
Mom* mommy = new Mom();
cout << "~~Made Mom\n";

//calls chores function from Mom class
pthread_create(&threads, NULL, &Mom::Mom_helper, mommy);
cout << "~~Created threads\n";

pthread_mutex_destroy(&jobMutex);
cout << "~~Destroyed threads\n";

return 0;
}

我做错了什么,我一直在寻找并将我的代码与其他人进行比较,这似乎是正确的。但它没有用。任何人都可以对这种情况有所了解吗?

1 个答案:

答案 0 :(得分:5)

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

您可能希望在pthread_mutex_destroy之前的某个地方拨打pthread_join

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