意外的数字输出
Unexpected number output
我正在尝试创建一个程序来解决使用 posix 线程的哲学家用餐问题。然而,我一开始就卡住了,因为 std :: cout << id + 1 << "PHILOSOPHER: thinking" << std :: endl; 的输出; ++我;不正确并且 id 取的值太大。请指出我的错误。
pthread_mutex_t mutexSpoon[PHILOSOPHERS];
pthread_t createThread(int number){
pthread_t id;
int rc = pthread_create(&id, NULL, philFunc, &number);
if(rc){
abort();
}
return id;
}
void *philFunc(void *arg){
srand(time(0));
int id = *(int*)arg;
int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
int rightSpoon = id;
int temp;
int i = 0;
while(i < 10){
usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;
}
return nullptr;
}
main.cpp
using namespace std;
extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];
int main(){
setlocale(LC_ALL, "rus");
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_init(&mutexSpoon[i], NULL);
vector<pthread_t> vecID(PHILOSOPHERS);
for(int i = 0; i < PHILOSOPHERS; ++i)
vecID[i] = createThread(i);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_join(vecID[i], NULL);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_destroy(&mutexSpoon[i]);
return 0;
}
线程函数使用地址作为参数,您将其作为地址传递给函数 createThread
- number
的局部变量。 argument 的生命周期应该不短于 thread,所以和 mutex 完全一样。使用您的代码片段作为基础,我创建了一个解决该问题的示例:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <pthread.h>
#include <unistd.h>
void *philFunc(void *arg);
#define PHILOSOPHERS 10
struct Philosopher {
pthread_mutex_t mutexSpoon;
pthread_t id;
int no;
};
Philosopher philosophers[PHILOSOPHERS] = {};
pthread_t createThread(int& number){
pthread_t id;
int rc = pthread_create(&id, NULL, philFunc, &number);
if(rc){
abort();
}
return id;
}
void *philFunc(void *arg){
srand(time(0));
int id = *(int*)arg;
int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
int rightSpoon = id;
int temp;
int i = 0;
while(i < 10){
usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;
}
return nullptr;
}
extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];
int main(){
setlocale(LC_ALL, "rus");
for(int i = 0; i < PHILOSOPHERS; ++i) {
pthread_mutex_init(&philosophers[i].mutexSpoon, NULL);
philosophers[i].no = i;
philosophers[i].id = createThread(philosophers[i].no);
}
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_join(philosophers[i].id, NULL);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_destroy(&philosophers[i].mutexSpoon);
return 0;
}
如您所见,现在每个线程都有自己的结构 Philosopher
,按应有的方式存储其数据。虽然 philosophers
这里是一个数组,但它可以是任何其他容器,只要它的元素足够长并且不会更改它们的地址(pthread mutex 的某些实现的要求)。
请注意 createThread(int& number)
现在通过引用获取其参数,因此表达式 &number
将获取实际对象位置的地址,而不是局部变量的地址。
如果使用 C++ 线程支持和 std::future
,此代码会更简单。
我正在尝试创建一个程序来解决使用 posix 线程的哲学家用餐问题。然而,我一开始就卡住了,因为 std :: cout << id + 1 << "PHILOSOPHER: thinking" << std :: endl; 的输出; ++我;不正确并且 id 取的值太大。请指出我的错误。
pthread_mutex_t mutexSpoon[PHILOSOPHERS];
pthread_t createThread(int number){
pthread_t id;
int rc = pthread_create(&id, NULL, philFunc, &number);
if(rc){
abort();
}
return id;
}
void *philFunc(void *arg){
srand(time(0));
int id = *(int*)arg;
int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
int rightSpoon = id;
int temp;
int i = 0;
while(i < 10){
usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;
}
return nullptr;
}
main.cpp
using namespace std;
extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];
int main(){
setlocale(LC_ALL, "rus");
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_init(&mutexSpoon[i], NULL);
vector<pthread_t> vecID(PHILOSOPHERS);
for(int i = 0; i < PHILOSOPHERS; ++i)
vecID[i] = createThread(i);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_join(vecID[i], NULL);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_destroy(&mutexSpoon[i]);
return 0;
}
线程函数使用地址作为参数,您将其作为地址传递给函数 createThread
- number
的局部变量。 argument 的生命周期应该不短于 thread,所以和 mutex 完全一样。使用您的代码片段作为基础,我创建了一个解决该问题的示例:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <pthread.h>
#include <unistd.h>
void *philFunc(void *arg);
#define PHILOSOPHERS 10
struct Philosopher {
pthread_mutex_t mutexSpoon;
pthread_t id;
int no;
};
Philosopher philosophers[PHILOSOPHERS] = {};
pthread_t createThread(int& number){
pthread_t id;
int rc = pthread_create(&id, NULL, philFunc, &number);
if(rc){
abort();
}
return id;
}
void *philFunc(void *arg){
srand(time(0));
int id = *(int*)arg;
int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
int rightSpoon = id;
int temp;
int i = 0;
while(i < 10){
usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;
}
return nullptr;
}
extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];
int main(){
setlocale(LC_ALL, "rus");
for(int i = 0; i < PHILOSOPHERS; ++i) {
pthread_mutex_init(&philosophers[i].mutexSpoon, NULL);
philosophers[i].no = i;
philosophers[i].id = createThread(philosophers[i].no);
}
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_join(philosophers[i].id, NULL);
for(int i = 0; i < PHILOSOPHERS; ++i)
pthread_mutex_destroy(&philosophers[i].mutexSpoon);
return 0;
}
如您所见,现在每个线程都有自己的结构 Philosopher
,按应有的方式存储其数据。虽然 philosophers
这里是一个数组,但它可以是任何其他容器,只要它的元素足够长并且不会更改它们的地址(pthread mutex 的某些实现的要求)。
请注意 createThread(int& number)
现在通过引用获取其参数,因此表达式 &number
将获取实际对象位置的地址,而不是局部变量的地址。
如果使用 C++ 线程支持和 std::future
,此代码会更简单。