C 在GDB中运行程序与从命令行运行程序的结果不同

C 在GDB中运行程序与从命令行运行程序的结果不同,c,debugging,gdb,C,Debugging,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

我把解决这个问题作为学校作业的一部分。当我用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);
    }
}
然后在命令行中启动它。 命令行输出:

        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中,我是这样运行的:

gcc -g sleeping_barber.c -o barber -lpthread
(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]
工作如我们的作业所述

信息:

OS->xubuntu-16.04.1


调试器->GNU gdb(Ubuntu 7.11.1-0ubuntu1~16.04)7.11.1

您的代码中有多个问题

如果客户无法进入理发店,您永远不会再次释放信号灯
sem_open1
sem_client
。 这就是为什么您的线程在等待sem_open1时明显被阻塞的原因。你可以扣除这一部分,因为在“我想要理发”之后没有更多的输出

但是如果我们从开头开始,我们会看到当您的第一个线程进入商店时,
open
必须为0,因为您的条件
if(open==1&&nr\u clients
为false。 由于还没有人增加
nr_客户端
,因此它必须是
打开的部分

此外,你可以只看一下你的产品:理发师还没有开店。 如果商店在第一次尝试时关闭,您可以添加一些逻辑以重试

问题的原因是您假定线程的执行顺序是确定的。从输出中的线程数可以很容易地看出,它不是您所期望的。你根本不能依赖任何命令

为了确保你的理发店开门营业,你需要在开始其他理发店的理发店之前,给理发店的理发店一个机会。创建理发师后,添加一些
sleep()

最后。。。
根据我所写的,你可能会得出结论,这一切都与时间有关。如果在调试器中或不使用调试器运行程序,则计时可能会大不相同。

代码中存在多个问题

如果客户无法进入理发店,您永远不会再次释放信号灯
sem_open1
sem_client
。 这就是为什么您的线程在等待sem_open1时明显被阻塞的原因。你可以扣除这一部分,因为在“我想要理发”之后没有更多的输出

但是如果我们从开头开始,我们会看到当您的第一个线程进入商店时,
open
必须为0,因为您的条件
if(open==1&&nr\u clients
为false。 由于还没有人增加
nr_客户端
,因此它必须是
打开的部分

此外,你可以只看一下你的产品:理发师还没有开店。 如果商店在第一次尝试时关闭,您可以添加一些逻辑以重试

问题的原因是您假定线程的执行顺序是确定的。从输出中的线程数可以很容易地看出,它不是您所期望的。你根本不能依赖任何命令

为了确保你的理发店开门营业,你需要在开始其他理发店的理发店之前,给理发店的理发店一个机会。创建理发师后,添加一些
sleep()

最后。。。
根据我所写的,你可能会得出结论,这一切都与时间有关。如果在调试器中或不使用调试器运行程序,则计时可能会大不相同。

该程序对我来说运行良好。Ubuntu 16.04/gdb 7.11.1/gcc 5.4.0该程序对我来说运行良好。Ubuntu 16.04/gdb 7.11.1/gcc 5.4.0感谢您的反馈。最后一段将解释这两个不同的结果。我想,在使用信号量时,假设订单是我最不应该做的事情。是的,如果你能确保一定的订单,那么你很可能不需要信号量但是线程运行时没有同步,也没有预定义的顺序,除非您采取措施这样做。谢谢您的反馈。最后一段将解释这两个不同的结果。我想,在使用信号量时,假设订单是我最不应该做的事情。是的,如果你能确保一定的订单,那么你很可能不需要信号量但是线程运行时没有同步,也没有预定义的顺序,除非您采取措施这样做。