2016-12-11 3 views
0

私は学校の割り当ての一部としてsleeping barber problemを解決していました。 GDBで実行するとうまく動作しますが、コマンドラインから実行するとスタックになります。これはコードです:GDBでプログラムを実行すると、コマンドラインからプログラムを実行したときとは異なる結果になる

#include <stdio.h> 
#include <semaphore.h> 
#include <pthread.h> 
#include <stdlib.h> 
#define MAX 5 

int nr_clients, open; 
sem_t sem_open1, sem_clients, sem_chair, sem_number; 

void *Barber(){ 
    sem_wait(&sem_open1); 
    printf("Barber: Opening the shop\n"); 
    open = 1; 
    sem_post(&sem_open1); 
    while(1){ 
     printf("Barber: Sleeping while there is no clients\n"); 
     sem_wait(&sem_clients); 
     sem_wait(&sem_number); 
     if(nr_clients > 0){ 
      sem_post(&sem_number); 
      printf("Barber: starting to work on a client\n"); 
      sem_post(&sem_chair); 
      sleep(1); 
      sem_wait(&sem_number); 
      printf("Barber: Client finished\n"); 
      nr_clients--; 
      sem_post(&sem_number); 
     } else { 
      printf("Barber: Closing the shop\n"); 
      break; 
     } 
    } 
} 


void *Client(void *x){ 
    int i = *((int*)x); 
    printf("%8sClient(%d): I want a haircut\n", "", i); 
    sem_wait(&sem_open1); 
    sem_wait(&sem_number); 
    if(open == 1 && nr_clients < MAX){ 
     sem_post(&sem_open1); 
     printf("%8sClient(%d): entering the shop\n", "", i); 
     nr_clients++; 
     sem_post(&sem_number); 
     sem_post(&sem_clients); 
     sem_wait(&sem_chair); 
     printf("%8sClient(%d): barber is working on me\n", "", i); 
    } else { 
     printf("No more room\n"); 
    } 
} 



int main(int argc, char const *argv[]) 
{ 
    if(sem_init(&sem_open1,0,1) == -1 || sem_init(&sem_clients,0,0) == -1 
     || sem_init(&sem_chair,0,0) == -1 || sem_init(&sem_number,0,1) == -1){ 
     printf("ERROR!\n"); 
     return 1; 
    } 

    int nr_threads = 5+1; 

    pthread_t thr_id[nr_threads]; 

    if(pthread_create(&thr_id[0], NULL, Barber, NULL) != 0) { 
     printf("ERROR!\n"); 
     exit(1); 
    } 

    int numbers[nr_threads-1]; 

    for (int i = 0; i < nr_threads-1; ++i) 
    { 
     numbers[i] = i; 
    } 

    for (int i = 1; i < nr_threads; ++i) 
    { 
     if(pthread_create(&thr_id[i], NULL, Client, &numbers[i-1]) != 0){ 
      printf("ERROR!\n"); 
      exit(1); 
     } 
    } 




    sleep(10); 

    sem_wait(&sem_open1); 
    open = 0; 
    sem_post(&sem_open1); 

    sem_post(&sem_clients); 

    for (int i = 0; i < nr_threads; ++i) 
    { 
     pthread_join(thr_id[i], NULL); 
    } 
} 

私はこのようにそれをコンパイルします。

gcc -g sleeping_barber.c -o barber -lpthread 

そして、ちょうど、コマンドラインでそれを開始します。 コマンドライン出力:

 Client(4): I want a haircut 
No more room 
     Client(3): I want a haircut 
     Client(2): I want a haircut 
     Client(1): I want a haircut 
     Client(0): I want a haircut 
^C 

それはちょうどそこに立ち往生。 GDBで

私はこのようにそれを実行します。

(gdb) file barber 
Reading symbols from barber...done. 
(gdb) r 
Starting program: /home/marko/Desktop/barber 

GDB出力:

[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 
[New Thread 0x7ffff77f0700 (LWP 2808)] 
Barber: Opening the shop 
Barber: Sleeping while there is no clients 
[New Thread 0x7ffff6fef700 (LWP 2809)] 
     Client(0): I want a haircut 
     Client(0): entering the shop 
Barber: starting to work on a client 
     Client(0): barber is working on me 
[New Thread 0x7ffff67ee700 (LWP 2810)] 
[Thread 0x7ffff6fef700 (LWP 2809) exited] 
     Client(1): I want a haircut 
     Client(1): entering the shop 
[New Thread 0x7ffff5fed700 (LWP 2811)] 
     Client(2): I want a haircut 
     Client(2): entering the shop 
[New Thread 0x7ffff57ec700 (LWP 2812)] 
     Client(3): I want a haircut 
     Client(3): entering the shop 
[New Thread 0x7ffff4feb700 (LWP 2813)] 
     Client(4): I want a haircut 
     Client(4): entering the shop 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(1): barber is working on me 
[Thread 0x7ffff67ee700 (LWP 2810) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(2): barber is working on me 
[Thread 0x7ffff5fed700 (LWP 2811) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(3): barber is working on me 
[Thread 0x7ffff57ec700 (LWP 2812) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(4): barber is working on me 
[Thread 0x7ffff4feb700 (LWP 2813) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: Closing the shop 
[Thread 0x7ffff77f0700 (LWP 2808) exited] 
[Inferior 1 (process 2804) exited normally] 

作品私たちの割り当てで説明したように。

INFO:

OS - > Xubuntuの-16.04.1

デバッガ - > GNU GDB(Ubuntuの7.11.1-0ubuntu1〜16.04)7.11.1

+0

プログラムはうまく動作します。 Ubuntu 16.04/gdb 7.11.1/gcc 5.4.0 – gobrewers14

答えて

2

あなたはあなたの中に複数の問題を持っていますコード。

クライアントがBarberの店に入ることができない場合は、セマフォーsem_open1sem_clientを再度解放しないでください。 これは、あなたのスレッドがsem_open1を待って明らかにブロックされている理由です。 「私はヘアカットをしたい」の後に出力がないので、これを差し引くことができます。

if(open == 1 && nr_clients < MAX)が偽であるため、最初のスレッドがショップに入ったときに、最初から開始すると、openが0である必要があります。 まだ増加していない人はnr_clientsなので、それはopenの部分でなければなりません。

あなたの出力を見てください。Barberはまだ店を開いていませんでした。 最初の試行時にショップが閉鎖されている場合は、もう一度試してください。

あなたの問題の理由は、スレッドが実行される特定の順序を前提としているためです。あなたの出力のスレッド番号で簡単に見ることができるように、あなたが期待したものではありません。どんな順序にも依存することはできません。

お店が開店していることを確認するには、Barberのスレッドに他のスレッドを開始する前に実行する必要があります。あなたの理容師を作成した後に、sleep()を追加してください。

最後に... 私が書いたことで、それはすべてのタイミングについての結論になるかもしれません。また、プログラムをデバッガで実行する場合、またはデバッガを使用しない場合は、タイミングが非常に異なる場合があります。

+0

フィードバックありがとうございます。あなたの最後の段落は、2つの異なる結果を説明します。私は、セマフォを使って作業するとき、私がやったはずの命令があると仮定していると思います。 – Marko

+0

はい、特定の順序を保証することができれば、セマフォーはほとんど必要ないでしょう。 ;)しかし、スレッドは同期化なしで実行され、事前に定義された順序はありません。 – Gerhardh

関連する問題