小弟昨天上OS的lab課
然後他給了一個有些哲學家會飢餓(starvation) 狀態的解法
要求我們另外寫一個沒有任何一個哲學家有飢餓(starvation) 狀態的解法
我今天在寫這道題的時候 想了很久都沒完成老師的要求
所以就去爬文看看有沒有滿足老師要求的code
結果真被我找到一個
找到的code:
//Submitted by : Ashutosh Soni
// Header file include
#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;
#define N 5
#define THINKING 2
#define HUNGRY 1
#define EATING 0
#define LEFT (phnum + (N-1)) % N
#define RIGHT (phnum + 1) % N
// Philosopher index
int phil[N];
int times = 5;
class monitor {
// state of the philosopher
int state[N];
// Philosopher condition variable
pthread_cond_t phcond[N];
// mutex variable for synchronization
pthread_mutex_t condLock;
public:
// Test for the desired condition
// i.e. Left and Right philosopher are not reading
void test(int phnum)
{
if (state[(phnum + 1) % 5] != EATING
and state[(phnum + 4) % 5] != EATING
and state[phnum] == HUNGRY) {
state[phnum] = EATING;
pthread_cond_signal(&phcond[phnum]);
}
}
// Take Fork function
void take_fork(int phnum)
{
pthread_mutex_lock(&condLock);
// Indicates it is hungry
state[phnum] = HUNGRY;
// test for condition
test(phnum);
// If unable to eat.. wait for the signal
if (state[phnum] != EATING) {
pthread_cond_wait(&phcond[phnum], &condLock);
}
cout << "Philosopher " << phnum +1 << " is Eating"
<< endl;
pthread_mutex_unlock(&condLock);
}
// Put Fork function
void put_fork(int phnum)
{
pthread_mutex_lock(&condLock);
// Indicates that I am thinking
state[phnum] = THINKING;
test(RIGHT);
test(LEFT);
pthread_mutex_unlock(&condLock);
}
// constructor
monitor()
{
for (int i = 0; i < N; i++) {
state[i] = THINKING;
}
for (int i = 0; i < N; i++) {
pthread_cond_init(&phcond[i], NULL);
}
pthread_mutex_init(&condLock, NULL);
}
// destructor
~monitor()
{
for (int i = 0; i < N; i++) {
pthread_cond_destroy(&phcond[i]);
}
pthread_mutex_destroy(&condLock);
}
}
// Global Object of the monitor
phil_object;
void* philosopher(void* arg)
{
int c = 0;
while (c < times) {
int i = *(int*)arg;
sleep(1);
phil_object.take_fork(i);
sleep(0.5);
phil_object.put_fork(i);
c++;
}
}
int main()
{
// Declaration...
pthread_t thread_id[N];
pthread_attr_t attr;
// Initialization...
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_JOINABLE);
for (int i = 0; i < N; i++) {
phil[i] = i;
}
// Creating...
for (int i = 0; i < N; i++) {
pthread_create(&thread_id[i], &attr, philosopher,
&phil[i]);
cout << "Philosopher " << i + 1 << " is thinking..."
<< endl;
}
// Joining....
for (int i = 0; i < N; i++) {
pthread_join(thread_id[i], NULL);
}
// Destroying
pthread_attr_destroy(&attr);
pthread_exit(NULL);
return 0;
}
然後啊 因為老師要求是C寫的 所以我就照這個code的想法去改
生出了以下的code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#define N 5
#define THINKING 2
#define HUNGRY 1
#define EATING 0
#define STATE int
#define LEFT (philosopher_number + 4) % 5
#define RIGHT (philosopher_number + 1) % 5
int state[5];
int times = 5;
int phil[5]={0,1,2,3,4};
pthread_t thread[5];
void *philosopher (void* num);
void test(int );
void pickup_chopstick(int );
void return_chopstick(int );
void test(int philosopher_number) {
if (state[(philosopher_number + 1) % 5] != EATING && state[LEFT] != EATING && state[RIGHT] == HUNGRY)
state[philosopher_number] = EATING;
}
void pickup_chopstick(int philosopher_number) {
int i = philosopher_number;
state[i] = HUNGRY;
test(i);
printf("The philosopher %d is eating\n", i+1);
}
void return_chopstick(int philosopher_number) {
state[philosopher_number] = THINKING;
test(LEFT);
test(RIGHT);
}
void *philosopher (void *num) {
int j;
int *i=(int *)num;
while (j<times) {
pickup_chopstick((intptr_t)i);
//eating();
sleep(1);
return_chopstick((intptr_t)i);
sleep(1);
j++;
}
}
int main(int argc, const char * argv[] ) {
int i ;
for ( i = 0 ; i < 5 ; i++) state[i] = THINKING;
for ( i = 0 ; i < 5 ; i++) pthread_create(&thread[i], NULL, philosopher,phil[i]);
for ( i = 0; i < 5; i++) pthread_join(thread[i],NULL);
pthread_exit(NULL);
return 0;
}
問題來了
上面那個code是可以正常執行的
但10幾分鐘前因為一個小地方然後不給我執行
如圖:
然後正常的是這樣:
呃 Imgur在搞誒 為什麼沒出現= =
前後唯一的差別是
錯的是這樣
pthread_create(&thread[i], NULL, philosopher,&phil[i])
對的是這樣
pthread_create(&thread[i], NULL, philosopher,phil[i])
但是上面那個C++卻是可以執行錯的那個
我很好奇明明都是用同一個library(pthread.h)為什麼C和C++有差別
求解!
我改了兩個地方,提供參考看看
1.pthread_create(&thread[i], NULL, philosopher,&phil[i])
2.pickup_chopstick(*i
);和return_chopstick(*i
);
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#define N 5
#define THINKING 2
#define HUNGRY 1
#define EATING 0
#define STATE int
#define LEFT (philosopher_number + 4) % 5
#define RIGHT (philosopher_number + 1) % 5
int state[5];
int times = 5;
int phil[5]={0,1,2,3,4};
pthread_t thread[5];
void *philosopher (void* num);
void test(int );
void pickup_chopstick(int );
void return_chopstick(int );
void test(int philosopher_number) {
// printf("test %d\n", philosopher_number);
if (state[(philosopher_number + 1) % 5] != EATING && state[LEFT] != EATING && state[RIGHT] == HUNGRY)
state[philosopher_number] = EATING;
}
void pickup_chopstick(int philosopher_number) {
int i = philosopher_number;
printf("The philosopher %d is eating\n", i);
state[i] = HUNGRY;
test(i);
}
void return_chopstick(int philosopher_number) {
// printf("return %d\n", philosopher_number);
state[philosopher_number] = THINKING;
test(LEFT);
test(RIGHT);
}
void *philosopher (void *num) {
int j;
int *i=(int *)num;
while (j<times) {
// printf("j:%d times:%d num:%d\n", j, times, *i);
// pickup_chopstick((intptr_t)i);
pickup_chopstick(*i);
//eating();
sleep(1);
// return_chopstick((intptr_t)i);
return_chopstick(*i);
sleep(1);
j++;
}
}
int main(int argc, const char * argv[] ) {
int i ;
int res;
for ( i = 0 ; i < 5 ; i++) {
// printf("thinking %d\n", i);
state[i] = THINKING;
}
for ( i = 0 ; i < 5 ; i++) {
// printf("creating %d\n", i);
res = pthread_create(&thread[i], NULL, philosopher, &phil[i]);
}
for ( i = 0; i < 5; i++) {
// printf("join %d\n", i);
pthread_join(thread[i],NULL);
}
pthread_exit(NULL);
return 0;
}
指標也好,*
也好
重點是function 定義的參數型態是什麼,就要傳什麼進去
C++部份
void take_fork(int phnum)
void put_fork(int phnum)
int i = *(int*)arg;
phil_object.take_fork(i);
phil_object.put_fork(i);
定義和傳進去的都是 int
C部份(你的版本)
void pickup_chopstick(int philosopher_number)
void return_chopstick(int philosopher_number)
int *i=(int *)num;
pickup_chopstick((intptr_t)i);
return_chopstick((intptr_t)i);
定義的是 int
傳進去的是 (intptr_t)
C部份(我改的版本)
void pickup_chopstick(int philosopher_number)
void return_chopstick(int philosopher_number)
int *i=(int *)num;
pickup_chopstick(*i);
return_chopstick(*i);
定義的是 int
傳進去也是 int
哦原來 是我疏忽了input的部分 真是謝謝你
OscarCS
其實只要將
int *i=(int *)num;
改回
int i= *(int *)num;
就能順利執行了。
使用指標技巧的時候應該注意 *
與 &
出現在不同地方會有不同的意義,例如:
int num = 10;
int *intPtr = # // 這裡的 * 表示 pointer to
int numCopy = *intPtr; // 這裡的 * 表示 value of