c - 执行的线程多于创建的线程

标签 c linux multithreading pthreads

我正在学习线程编程。在执行以下示例时,我遇到了未定义的行为。

static void* print_thread_attr (void* param)
{
    pthread_attr_t attr;
    int detach_state = PTHREAD_CREATE_JOINABLE;

    pthread_getattr_np (pthread_self(), &attr);
    pthread_attr_getdetachstate (&attr, &detach_state);
    pthread_attr_destroy (&attr);

    printf("Detach state of thread [%u] pid [%d] is %s\n", pthread_self(), getpid(),
            (PTHREAD_CREATE_JOINABLE == detach_state)?
                    "JOINABLE THREAD":"DETACHED THREAD");
    return NULL;
}

void test_thread_attributes ()
{
    pthread_t thread_id1;
    pthread_t thread_id2;
    pthread_attr_t attr;

    printf("main pid [%d]\n", getpid());
    pthread_attr_init (&attr);
    pthread_create (&thread_id1, &attr, print_thread_attr, NULL);

    pthread_attr_init (&attr);
    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    pthread_create (&thread_id2, &attr, print_thread_attr, NULL);

    pthread_attr_destroy (&attr);
    pthread_join (thread_id1, NULL);

    //sleep (1);
}

1.有时,它会打印:

main pid [3394]
Detach state of thread [88292160] pid [3394] is DETACHED THREAD
Detach state of thread [75705152] pid [3394] is JOINABLE THREAD
  1. 但有时

     main pid [3403]
     Detach state of thread [75705152] pid [3403] is JOINABLE THREAD
     Detach state of thread [88292160] pid [3403] is DETACHED THREAD
     Detach state of thread [88292160] pid [3403] is DETACHED THREAD
    

这很奇怪,因为我只使用了 2 次 pthread_create,但第二种情况打印了 3 次。在使用valgrind检查时,第一种情况没有内存泄漏,但对于第二种情况,“可能丢失:1个 block 中的136字节”

我需要知道为什么在第二种情况下,线程 88292160 打印两次? 此外,您可能会注意到注释掉的 sleep (1)。当我 sleep 时 (1),我没有观察到第二种情况发生。

最佳答案

调用 pthread_attr_init() 后出现未定义行为两次和第二次在一个已经初始化的对象上:

Calling pthread_attr_init() on a thread attributes object that has already been initialized results in undefined behavior.

对象 attr 被销毁后可以重用:

Once a thread attributes object has been destroyed, it can be reinitialized using pthread_attr_init(). Any other use of a destroyed thread attributes object has undefined results.

但是,您的代码中无法保证该属性会在第二个线程重新初始化之前被第一个线程销毁。因此,您可以使用两个不同的属性对象,甚至可以重复使用相同的属性(无需重新初始化)。但是,由于您在线程中销毁了该属性,因此该选项在您的代码中是不可能的。

最新POSIX standard但是,删除了用于重新初始化已初始化但已销毁的属性和状态的引用未定义行为:

If an implementation detects that the value specified by the attr argument to pthread_attr_init() refers to an already initialized thread attributes object, it is recommended that the function should fail and report an [EBUSY] error.

我假设您的实现使用了一些旧版本并导致未定义的行为。无论如何,这是一个问题,您应该检查 pthread 函数的返回值是否有错误。

看到的重复输出的实际问题是由于实现 issue with the stdio这在 an answer 中有解释。在这里可以解释为什么 sleep 似乎可以“解决”问题以及避免此问题的可能解决方法。

关于c - 执行的线程多于创建的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30096816/

相关文章:

c - C 字符串中的空字符

ios - 如何回滚临时上下文的更改?

在构建时检查 C 类型的大小

谁能在 DAC 的以下场景中帮助我

c - 如何从 clang 获取更细粒度的行/列调试信息?

c - _beginthread 与 CreateThread

WPF 在单独的线程中运行动画

jquery - 如何在 HTML/jquery 中为 Linux 终端生成 256 色调色板

linux - 如何使用 udev 使用自定义目录填充/dev

linux - 如何在 Debian Linux 中将 Clang 编译器从版本 3.1 更新到版本 3.4?