栈在使用Pthread的多线程程序中是如何工作的?
How does the stack work in multithreaded programs using Pthread?
我有一个简单的问题,据我所知,一个多线程程序,它们在所有线程之间共享进程的内存space,包括堆栈、全局内存区域、文件描述符等,我想知道为什么在第一个例子中,存在一致性问题,因为理论上所有线程共享堆栈,在第二个例子中,出现竞争问题。
#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;
}
share the process's memory space between all threads, that includes, stack
好吧,是也不是。
共享内存地址space和特定内存区域是有区别的。
虽然所有线程确实共享一个地址 space,但每个线程都有 自己的堆栈(内存分配)。
共享地址space表示给定的虚拟地址(指针值)在所有线程中指代相同的物理内存。
但是专用堆栈意味着每个线程的堆栈指针都从该地址的不同位置开始space,以免彼此冲突。
进程中的每个线程通常都有自己的堆栈指针(意味着它有自己的堆栈)。
这意味着当它们共享虚拟地址 space 时,允许它们访问其他线程的变量甚至堆栈,它们通常在这个共享虚拟内存的不同、不重叠的地方有自己的堆栈 space.
当内核调度一个线程时,它会将线程的寄存器安装在内核中或 cpu 它将要使用(这包括每个线程的堆栈指针,其值为堆栈)确实,内核为每个线程维护一个用户模式堆栈,还有一个内核堆栈(这最后允许同一进程的两个不同线程同时执行系统调用——相同或不同--,如果他们必须共享一个堆栈,这是不可能的)
我有一个简单的问题,据我所知,一个多线程程序,它们在所有线程之间共享进程的内存space,包括堆栈、全局内存区域、文件描述符等,我想知道为什么在第一个例子中,存在一致性问题,因为理论上所有线程共享堆栈,在第二个例子中,出现竞争问题。
#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;
}
share the process's memory space between all threads, that includes, stack
好吧,是也不是。
共享内存地址space和特定内存区域是有区别的。
虽然所有线程确实共享一个地址 space,但每个线程都有 自己的堆栈(内存分配)。
共享地址space表示给定的虚拟地址(指针值)在所有线程中指代相同的物理内存。
但是专用堆栈意味着每个线程的堆栈指针都从该地址的不同位置开始space,以免彼此冲突。
进程中的每个线程通常都有自己的堆栈指针(意味着它有自己的堆栈)。
这意味着当它们共享虚拟地址 space 时,允许它们访问其他线程的变量甚至堆栈,它们通常在这个共享虚拟内存的不同、不重叠的地方有自己的堆栈 space.
当内核调度一个线程时,它会将线程的寄存器安装在内核中或 cpu 它将要使用(这包括每个线程的堆栈指针,其值为堆栈)确实,内核为每个线程维护一个用户模式堆栈,还有一个内核堆栈(这最后允许同一进程的两个不同线程同时执行系统调用——相同或不同--,如果他们必须共享一个堆栈,这是不可能的)