我正在嘗試使用互斥鎖解決哲學家就餐問題,但是該程式可能會出現與執行緒相關的錯誤的段錯誤
我在這里要做的基本上是將叉子視為互斥鎖并創建一個函式void *eat(void *arg),然后關閉臨界區(臨界區只是宣告它的 id 并且它當前正在吃東西的執行緒)無論呼叫什么函式,然后我遍歷我所有的哲學家并檢查它的 id(id 從 0 開始)是否可被 2 整除.
第一輪只有執行緒 id 可以被 2 整除,第二輪只有執行緒 id 不能被 2 整除,以此類推。
我知道這是一個愚蠢的簡單解決方案,它可能一開始就無法解決問題。所以請多多包涵。如果您有任何問題,請在評論中告訴我。
struct typedef t_philo
{
pthread_t thread;
pthread_mutex_t fork;
int id;
}
t_philo;
void *eat(void *arg)
{
t_philo *philo = (t_philo *)arg;
pthread_mutex_lock(&philo->fork);
printf("philo with id: %i is eating\n", philo->id);
pthread_mutex_unlock(&philo->fork);
return (NULL);
}
void first_round(t_philo *philo, int len)
{
for (int i = 0; i < len; i )
if (!(i % 2))
pthread_join(philo[i].thread, NULL);
}
void second_round(t_philo *philo, int len)
{
for (int i = 0; i < len; i )
if ((i % 2))
pthread_join(philo[i].thread, NULL);
}
int main(int argc, char **argv)
{
t_philo *philo;
// how many philosophers is given as first arg.
int len = atoi(argv[1]);
if (argc < 2)
exit(EXIT_FAILURE);
philo = malloc(sizeof(*philo) * atoi(argv[1]));
//this function add id's and initialize some data.
init_data(philo, argv);
for (int i = 0; i < len; i )
pthread_create(&philo[i].thread, NULL, eat(&philo[i]), &philo[i]);
while (1)
{
first_round(philo, len);
second_round(philo, len);
}
return 0;
}
輸出
philo with id: 0 is eating
philo with id: 1 is eating
philo with id: 2 is eating
philo with id: 3 is eating
philo with id: 4 is eating
.
.
.
.
philo with id random is eating
[1] 29903 segmentation fault
輸出每次都達到一個隨機 id 和段錯誤,這就是為什么我斷定它可能是一個執行緒錯誤。
uj5u.com熱心網友回復:
pthread_create有以下原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
start_routine是一個函式指標。但是,您pthread_create使用錯誤的引數呼叫: eat(&philo[i])。因此,程式eat正確呼叫,然后嘗試(從新執行緒)呼叫,因為這是NULLeat. 隨機性來自實際創建執行緒的可變時間。
請注意,使用除錯器應該可以幫助您非常輕松地找到并修復問題。像 gdb 這樣的除錯器有點難學,但是一旦完成,像 segfault 這樣的錯誤就變得幾乎很容易修復。我也很驚訝像 clang 這樣的編譯器在編譯時不會注意到打字問題。
uj5u.com熱心網友回復:
在main,int len = argv[1];是錯誤的。如果您在啟用警告的情況下進行編譯(例如-Wall),該陳述句將被編譯器標記。
照原樣,您將獲得巨大的價值len。因此,稍后,for回圈將溢位您分配的陣列并且您擁有 UB。
您可能想要:int len = atoi(argv[1]);就像您對malloc.
而且,您想在檢查后argc執行此操作。
而且,為什么要呼叫atoi兩次 [with the fix]?
這是重構的代碼:
int
main(int argc, char **argv)
{
t_philo *philo;
if (argc < 2)
exit(EXIT_FAILURE);
// how many philosophers is given as first arg.
int len = atoi(argv[1]);
philo = malloc(sizeof(*philo) * len);
// do stuff ...
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/447436.html
