2012-07-10 79 views
-3

我使用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; 
} 

难道我做错了什么,我一直在寻找所有和我的代码跟别人作比较,它似乎是正确的。但它不起作用。任何人都可以看到这种情况?

+0

这将有助于有一个小例子来展示这个问题。 – 2012-07-10 20:58:11

+0

486行代码。真的吗? – 2012-07-10 20:58:48

+0

这差不多有500行代码。如果你将这个问题简化成一个展示问题的小程序,你很可能会得到答复。另外,尝试用'-Wall'编译。您列出的编译命令不会启用任何警告。 – bta 2012-07-10 21:01:25

回答

5

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

您可能想拨打pthread_join,在pthread_mutex_destroy之前的某处。

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

是正确的。你需要一个pthread_join()来等待启动的线程返回,或者在线程启动后进行某种无限循环。这真的是一个很好的地方,可以粘贴运行并等待,运行和等待的有用东西。 – 2012-07-10 21:03:54