1 内存中一地址,同一时间,只能被单一线程访问还是可以被多线程并行访问
2 开发一个程序的所有线程都在一个核心里执行还是可以被多核分开执行
3 程序中新开一个线程执行静态方法是将另外分一片内存同时将方法copy过去吗
1 内存中一地址,同一时间,只能被单一线程访问还是可以被多线程并行访问
对于x86这样的共享存储,竞争总线的方式,“同一时间”,当然只能有一个线程访问。但是要明确,可能其他线程会访问这个内存数据的脏数据的缓存,也可能因为对内存的访问缺乏原子性而存在同步问题。
2 开发一个程序的所有线程都在一个核心里执行还是可以被多核分开执行
如果这些线程没有相关性,那么OS会调度它们在多个内核/处理器上运行。
3 程序中新开一个线程执行静态方法是将另外分一片内存同时将方法copy过去吗
当然不是,不同的线程拥有自己的线程上下文(其实就是寄存器值)和自己的堆栈,至于代码,是共享的。
是这样的,现代的处理器具有缓存,甚至多层次的缓存,如果多个线程要同时访问同一个内存的数据,那么为了保证程序不出错,所有的线程都必须等待,不是说不能访问,而是说这样做的代价很高。我们假设你的程序中有1/10的cpu时间在访问这个内存的数据,你有32个并行的线程,那么很显然,你的理论性能上限较之单线程程序为1/(0.9/32+0.1)=7.8,而且随着处理器的增多,这样的浪费更大,无论你采用1百个CPU还是1万个CPU,都不可能超过10。而我们理想中期待如果有32个CPU,那么程序能快32倍,如果有128个CPU能快128倍。
问题三我说了,操作系统只为每个线程开辟线程上下文和堆栈的空间。
注意我说的是1/10的cpu时间,如果你有100行代码,有1行访问了竞争的内存,那么因为内存访问需要的周期远远超过寄存器存取和指令,那么cpu时间都会超过1/10。而且由于缓存同步的需要,程序实际上执行的更慢。甚至可能出现,用2个cpu还算不过1个cpu的情况。
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。每个C ++对象的数据成员也存在在栈中,每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放
下面举一个例子来加深理解。
随着面向对象编程方法的普及,我们很乐意将任何操作都包装成为一个类。线程函数也不例外,以静态函数的形式将线程函数放在类中是C++编程普遍使用的一种方法。通常情况下对象包括属性(类变量)与方法(类函数)。属性指明对象自身的性质,方法用于操作对象,改变它的属性。现在有一个小问题要注意了。类的静态函数只能访问类的静态变量,而静态变量是不属于单个对象的,他存放在进程的全局数据存储区。一般情况下,我们希望每个对象能够“独立”,也就是说,多个对象能够各自干各自的工作,不要相互打扰。如果以通常的方法,以类(静态)变量存储对象的属性,可就要出问题了,因为类(静态)变量不属于单个对象。现在怎么办呢?如何继续保持每个对象的“独立性”。解决的方法就是使用栈,将参数传递给线程函数的局部变量(栈存储区),以单个对象管理每个线程,问题就解决了。当然了,解决方法是多种多样的,这里只是为了进一步解释多线程与对象的关系。