多线程竞争内存

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寄存器。栈空间不需要在高级语言里面显式的分配和释放

总结: java局部变量中存的是对象引用,单例情况下 没有类共享变量的情况下, 每个方法的执行 内部是局部变量,由线程执行这个方法,互不影响;代码是共享的,但每个线程方法栈中的局部变量参数是不一样的。

每一个线程都独立拥有一个栈,多个线程可以“同时”执行。CPU执行程序代码完全依靠各种寄存器。当一个线程将被挂起时,当前的各种寄存器的数值就被存储在了线程的栈中。当CPU重新执行此线程时,将从栈中取出寄存器的数值,接着运行,好像这个线程从来就没有被打断过一样。正是因为每个线程都有一个独立的栈,使线程拥有了可以“闭门造车”的能力。只要将参数传递给线程的栈,CPU将担负起这块内存存储区的管理工作,并适时地执行线程函数代码对其进行操作。当系统在多个线程间切换时,CPU将执行相同的代码操作不同的栈。
下面举一个例子来加深理解。
随着面向对象编程方法的普及,我们很乐意将任何操作都包装成为一个类。线程函数也不例外,以静态函数的形式将线程函数放在类中是C++编程普遍使用的一种方法。通常情况下对象包括属性(类变量)与方法(类函数)。属性指明对象自身的性质,方法用于操作对象,改变它的属性。现在有一个小问题要注意了。类的静态函数只能访问类的静态变量,而静态变量是不属于单个对象的,他存放在进程的全局数据存储区。一般情况下,我们希望每个对象能够“独立”,也就是说,多个对象能够各自干各自的工作,不要相互打扰。如果以通常的方法,以类(静态)变量存储对象的属性,可就要出问题了,因为类(静态)变量不属于单个对象。现在怎么办呢?如何继续保持每个对象的“独立性”。解决的方法就是使用栈,将参数传递给线程函数的局部变量(栈存储区),以单个对象管理每个线程,问题就解决了。当然了,解决方法是多种多样的,这里只是为了进一步解释多线程与对象的关系。

时间: 2024-10-13 20:29:30

多线程竞争内存的相关文章

多线程访问共享内存的不加锁实现方式

http://blog.csdn.net/alane1986/article/details/6887359 多线程访问共享内存,为了实现同步,常采用加锁的方式. 那么,如何采用不加锁的方式来达到线程同步的目的呢? 思路: 保存两块共享内存,一块用于读操作,一块用于写操作. 初始时,两块共享内存内容一致.读操作均是读取第一块共享内存的数据:写操作均是写第二块共享内存. 在多个读操作一个写操作的情况下,读操作均从第一块共享内存读取,写操作修改第二块共享内存的数据.直至写操作完成,交换两块共享内存的

java多线程03-----------------volatile内存语义

java多线程02-----------------volatile内存语义 volatile关键字是java虚拟机提供的最轻量级额的同步机制.由于volatile关键字与java内存模型相关,因此,我们在介绍volatile关键字之前,对java内存模型进行更多的补充(之前的博文也曾介绍过). 1. java内存模型(JMM) JMM是一种规范,主要用于定义共享变量的访问规则,目的是解决多个线程本地内存与共享内存的数据不一致.编译器处理器的指令重排序造成的各种线程安全问题,以保障多线程编程的原

[读书笔记]iOS与OS X多线程和内存管理 [GCD部分]

3.2 GCD的API 苹果对GCD的说明:开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中. "Dispatch Queue"是执行处理的等待队列.通过dispatch_async函数等API,在Block语法中记述想执行的处理并追加到Dispatch Queue中,Dispatch Queue按照追加的顺序,执行处理. Dispatch Queue分为两种: 种类 说明 Serial Dispatch Queue 等待现在执行中处理结束(顺序执行) Co

java多线程12.内存模型

假设一个线程为变量赋值:variable = 3: 内存模型需要解决一个问题:"在什么条件下,读取variable的线程将看到这个值为3?" 这看上去理所当然,但是如果缺少内存同步,那么将会有许多因素使得线程无法立即甚至永远,看到另一个线程的操作结果. 如: 1.在编译器中生成的指令顺序,可以与源代码中的顺序不同,此外编译器还会将变量保存在寄存器而不是内存中: 2.处理器可以采用乱序或并行等方式来执行指令: 3.缓存可能会改变将写入变量提交到主内存的次序: 4.而且保存在处理器本地缓存

java多线程之内存可见性-synchronized、volatile

1.JMM:Java Memory Model(Java内存模型) 关于synchronized的两条规定: 1.线程解锁前,必须把共享变量的最新值刷新到主内存中 2.线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁和解锁需要是同一把锁) 注:线程解锁前对共享变量的修改在下次加锁时对其他线程可见 2.线程执行互斥代码的过程: 1.获得互斥锁 2.清空工作内存 3.从主内存拷贝变量的最新副本到工作内存 4.执行代码 5.将更改后的共享变量的值刷

Java多线程-Java内存模型

以下内容转自http://ifeve.com/java-memory-model-6/: Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型. 如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的.Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量. 原始的Java内存模型存在一些不足,因此Java内存模型在

JavaSE学习53:细说多线程之内存可见性

一共享变量在线程间的可见性 (1)有关可见性的一些概念介绍 可见性:一个线程对共享变量值的修改,能够及实地被其他线程看到. 共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量.所 有的变量都存储在主内存中. 线程的工作内存:每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中该变量的 一份拷贝). (2)数据争用问题 多个线程对同一资源操作时,通常会产生进程,比如一个线程往消息队列插入数据,而另一个线程从消息队列取 出数据 当消息队

java多线程与内存可见性

一.java多线程 JAVA多线程实现的三种方式: http://blog.csdn.net/aboy123/article/details/38307539 二.内存可见性 1.什么是JAVA 内存模型 共享变量 :如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量. Java Memory Model (JAVA 内存模型)描述线程之间如何通过内存(memory)来进行交互,描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存

多线程竞争

在多线程编程中,会经常碰到资源竞争的情况,如果多个线程同时访问同个资源,会照成未知的错误. 如以下实例代码,多个线程对同个全局变量进行加1操作,得到的结果并非是我们想要的结果: unsigned long g_count_num = 0; long long getSystemTime() { struct timeb t; ftime(&t); return 1000 * t.time + t.millitm; } void * pth_test_fun(void * a_arg) { int