iT邦幫忙

0

為什麼C和C++ 執行pthread_create有差別

c c++
  • 分享至 

  • twitterImage

小弟昨天上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

然後正常的是這樣:
Imgur

呃 Imgur在搞誒 為什麼沒出現= =

前後唯一的差別是
錯的是這樣

pthread_create(&thread[i], NULL, philosopher,&phil[i])

對的是這樣

pthread_create(&thread[i], NULL, philosopher,phil[i])

但是上面那個C++卻是可以執行錯的那個
我很好奇明明都是用同一個library(pthread.h)為什麼C和C++有差別
求解!

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

2
海綿寶寶
iT邦大神 1 級 ‧ 2021-11-21 09:54:05
最佳解答

https://ithelp.ithome.com.tw/upload/images/20211121/20001787AlYGRmHPym.png

我改了兩個地方,提供參考看看
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;
}
看更多先前的回應...收起先前的回應...
OscarCS iT邦新手 5 級 ‧ 2021-11-21 10:43:31 檢舉

哦哦哦 你改了那個intptr_t
不過intptr_t 是什麼東東啊?為什麼ptr不是指標的意思嗎和*有什麼差別嗎? intptr_t我是從老師給的範例抄下來的 沒想到是這個指標出問題

指標也好,*也好
重點是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
OscarCS iT邦新手 5 級 ‧ 2021-11-22 21:14:06 檢舉

哦原來 是我疏忽了input的部分 真是謝謝你

EN iT邦好手 1 級 ‧ 2021-11-23 00:31:59 檢舉

OscarCS
其實只要將

int *i=(int *)num;

改回

int i= *(int *)num;

就能順利執行了。
使用指標技巧的時候應該注意 *& 出現在不同地方會有不同的意義,例如:

int num = 10;
int *intPtr = &num; // 這裡的 * 表示 pointer to
int numCopy = *intPtr; // 這裡的 * 表示 value of

我要發表回答

立即登入回答