c++ - 使用多线程编程,不打印预期输出

标签 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;
}

我做错了什么吗?我已经仔细查看并将我的代码与其他代码进行比较,它似乎是正确的。但它不起作用。谁能解释一下这种情况?

最佳答案

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

您可能需要调用pthread_joinpthread_mutex_destroy 之前的某处。

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

关于c++ - 使用多线程编程,不打印预期输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11421775/

相关文章:

linux - 启动时如何加载模块?它们在启动时加载的顺序是什么?怎么改?

c - inode实际上是否指向磁盘中的地址?

c++ - 相同的线程 ID

c++ - 获取参数包中函数指针的返回类型并将其保存为与其他参数的连接元组

c++ - 右侧资源管理器上下文菜单(IID_IContextMenu?)

c++ - boost::process::env 在 ubuntu 19.04 上损坏了?

c++ - 带有数组 C++ 的静态 int

linux - 含义 警告 "File is touched by more than one package"

c - 什么是 C 语言的线程安全 DBM 库?

c - 线程处理程序上的段错误