【问题标题】:How does the stack work in multithreaded programs using Pthread?堆栈如何在使用 Pthread 的多线程程序中工作?
【发布时间】:2021-11-09 04:39:30
【问题描述】:

我有一个简单的问题,据我所知,我相信一个多线程程序,它们在所有线程之间共享进程的内存空间,包括堆栈、全局内存区域、文件描述符等,II想知道为什么在第一个例子中,存在一致性问题,因为理论上所有线程共享堆栈,在第二个例子中,出现竞争问题。

#include <stdio.h>
#include <pthread.h>

void *thr(void *arg)
{
   for(int i = 0; i < 50; i++)
       printf("Thread = %zu Value= %d\n", pthread_self(), i);
   return NULL;
}

int main(void)
{
   pthread_t threads[2];
   for(int i = 0; i < 2; i++)
     pthread_create(&threads[i], NULL, thr, NULL);
   for(int i = 0; i < 2; i++)
     pthread_join(threads[i], NULL);
   return 0;
}

第二个程序有运行问题

#include <stdio.h>
#include <pthread.h>

int i = 0;

void *thr(void *arg)
{
   for(; i < 50; i++)
     printf("Thread = %zu Value= %d\n", pthread_self(), i);
   return NULL;
}

int main(void)
{
   pthread_t threads[2];
   for(int i = 0; i < 2; i++)
     pthread_create(&threads[i], NULL, thr, NULL);
   for(int i = 0; i < 2; i++)
     pthread_join(threads[i], NULL);
   return 0;
}

3 有竞争问题的例子,在这种情况下,变量是在主线程中创建的,并作为参数传递给函数,也就是说,唯一的共享堆栈来自主线程?

#include <stdio.h>
#include <pthread.h>

void *thr(void *arg)
{
   int *ptr = (int *)arg;
   for(; *ptr < 50; (*ptr)++)
     printf("Thread = %zu Value= %d\n", pthread_self(), *ptr);
   return NULL;
}

int main(void)
{
   int i = 0;
   pthread_t threads[2];
   for(int i = 0; i < 2; i++)
     pthread_create(&threads[i], NULL, thr, &i);
   for(int i = 0; i < 2; i++)
     pthread_join(threads[i], NULL);
   return 0;
}

【问题讨论】:

    标签: c multithreading pthreads posix thread-synchronization


    【解决方案1】:

    在所有线程之间共享进程的内存空间,包括堆栈

    嗯,是的,也不是。

    共享一个内存地址空间和一个特定的内存区域是有区别的。

    虽然所有线程确实共享一个地址空间,但每个线程都有自己的堆栈(内存分配)。

    共享地址空间意味着给定的虚拟地址(指针值)在所有线程中引用相同的物理内存。

    但是专用堆栈意味着每个线程的堆栈指针在该地址空间中的不同位置开始,以免相互冲突。

    【讨论】:

    • 主线程栈是否共享?因为当我将它作为参数传递时,其他线程可以访问它,但是当我在堆栈上的另一个线程中创建变量时,它不是共享的,这似乎是
    • 堆栈都存在于同一个地址空间中,但该空间内的区域是分开的。
    • @YuriBittencourt:所有线程都可以访问所有其他线程的堆栈,因为它们在同一个virtual address space中。例如,如果一个线程被传递一个指向另一个线程堆栈上的变量的指针,它可以不受任何限制地访问该变量(尽管可能会降低性能,因为CPU cache 的工作方式)。
    • 为什么在第一个例子中,变量i,似乎n对其他线程可见,而在第三个例子中,变量i对其他线程可见?
    • @AndreasWenzel ?
    【解决方案2】:

    进程中的每个线程通常都有自己的堆栈指针(意味着它有自己的堆栈)。

    这意味着虽然它们共享虚拟地址空间,使它们能够访问其他线程的变量甚至堆栈,但它们通常在此共享虚拟内存空间的不同、非重叠位置拥有自己的堆栈。

    当内核调度一个线程时,它会将线程的寄存器安装在将要使用的内核或 cpu 中(这包括每个线程的堆栈指针,其值为 stack)事实上,内核维护一个用户模式堆栈对于每个线程还有一个内核堆栈(这最后允许同一进程的两个不同线程同时执行系统调用——相同或不同——,这不会是如果他们必须共享一个堆栈,则可能)

    【讨论】:

    • 你很受欢迎! :)
    猜你喜欢
    • 2022-08-06
    • 2020-02-12
    • 2014-09-14
    • 2018-04-08
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2021-05-21
    • 2012-11-14
    相关资源
    最近更新 更多