d*********g 发帖数: 38 | 1 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。
举个栗子:
class M extends Thread{
int mValue=0;
public void run(){...}
}
class N extends Thread{
int nValue=1;
public void run{...}
}
class Main{
int mainValue=2;
public static void main(){
Thread m1=new M();
Thread m2=new M();
Thread n=new N();
}
}
这个例子中,Main是主进程吗?可以被m1, m2, n共享的进程空间包括什么?
我的理解有几种可能:
1. m1和m2可以共享mValue ,虽然mValue不是static的。不过我不确定这种共享是否基
于同一进程地址空间。
2. m1, m2, 和 n1可以共享mainValue (因为Main是线程,m1, m2, n1都是该线程下的
进程)。 |
p*****2 发帖数: 21240 | 2
1不行吧?
【在 d*********g 的大作中提到】 : 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。 : 举个栗子: : class M extends Thread{ : int mValue=0; : public void run(){...} : } : class N extends Thread{ : int nValue=1; : public void run{...} : }
|
d*********g 发帖数: 38 | 3 你这一说我也糊涂了,我觉得2似乎也不行。这样一来,两个相同class的线程(比如m1
m2)能共享什么呢?如果是两个不同class的线程呢?(比如m1和n)。
【在 p*****2 的大作中提到】 : : 1不行吧?
|
d******e 发帖数: 2265 | 4 浆糊啊。
第一,搞清楚value和refer类型。value类型, int,是在stack上。不可能被共享。
所以,下面一个都不会被共享。
第二,一般共享的是某个类里面的某个变量。通过这个类的某个方法来实现共享。
【在 d*********g 的大作中提到】 : 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。 : 举个栗子: : class M extends Thread{ : int mValue=0; : public void run(){...} : } : class N extends Thread{ : int nValue=1; : public void run{...} : }
|
k*****u 发帖数: 136 | 5 我才楼主是半路出家吧
建议楼主搞清楚几个概念,进程 线程 堆 栈
什么变量存在堆中,什么变量存在栈中
为什么线程之间不能互相共享(存储在各自线程的private栈里)
为什么进程里面的变量可以被线程访问(存储在主进程的共享栈里)
所以1 是不行的,每一个实例化的m都各自含有一个mvalue 彼此独立
2你自己查查吧 写个程序就知道了 |
c*********e 发帖数: 16335 | 6 线程 和 进程 都没搞清。你半路出家的吧?
【在 d*********g 的大作中提到】 : 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。 : 举个栗子: : class M extends Thread{ : int mValue=0; : public void run(){...} : } : class N extends Thread{ : int nValue=1; : public void run{...} : }
|
d*********g 发帖数: 38 | 7 的确是半路出家,刚开始看多线程,一团雾水,感谢楼上几位。
那很多资料都写到“All threads of a process share its virtual address space
and system resources.”或类似的意思,这个share有什么好处呢,既然每个线程都有
自己的私有栈。 |
g*********e 发帖数: 14401 | 8 你这个也不对 java obj怎么会在stack上
【在 d******e 的大作中提到】 : 浆糊啊。 : 第一,搞清楚value和refer类型。value类型, int,是在stack上。不可能被共享。 : 所以,下面一个都不会被共享。 : 第二,一般共享的是某个类里面的某个变量。通过这个类的某个方法来实现共享。
|
z****e 发帖数: 54598 | 9
int是primitive type,不是obj,obj是Integer
还有如果我记得没错,某人说过,local inner object好像是会被放到stack里面去
好久了不太记得了,反正不是百分百obj都不会放到stack上去的
某些特殊情况下优化,就会被放进去,但是这些都属于奇淫技巧
不懂没啥关系
【在 g*********e 的大作中提到】 : 你这个也不对 java obj怎么会在stack上
|
k*****u 发帖数: 136 | 10 share的好处就是 high performance
举个例子,如果你的计算机有多个core,比如说四核,那么理论上四个core可以同时进
行计算
你有一个process,你需要处理一款很大的数据,你就把这个数据没成四块,然后
create四个thread,每个线程都去计算各自的数据,然后把数据汇总到进程中。这个过
程数据从进程到线程,再由线程回进程,就是一个共享的结果
当然share的好处不局限于此
如果是自己的pc也许只有四核 八核,如果是集群可能就是几十核,几百核,有很多高
性能的技术比如openmp(shared memory) openmpi(message passing) hadoop(
mapreduce) 都是类似的进行计算,大同小异
敢问一句,楼主开始cs的东西多久了? 说说你的打算,比起技术上的细节,最重要的
学习的方法
【在 d*********g 的大作中提到】 : 的确是半路出家,刚开始看多线程,一团雾水,感谢楼上几位。 : 那很多资料都写到“All threads of a process share its virtual address space : and system resources.”或类似的意思,这个share有什么好处呢,既然每个线程都有 : 自己的私有栈。
|
|
|
d******e 发帖数: 2265 | 11 int不是obj.要变obj需要boxing/unboxing.事实上很多情况下int放在register里面。
如果都要unbox一下在放register计算,java的效率估计还不如python呢。
【在 g*********e 的大作中提到】 : 你这个也不对 java obj怎么会在stack上
|
g*****g 发帖数: 34805 | 12 没有 declare成Integer, 会放在 stack上。至于 是否用register, 是 JVM级别的处理
,没法控制。
【在 d******e 的大作中提到】 : int不是obj.要变obj需要boxing/unboxing.事实上很多情况下int放在register里面。 : 如果都要unbox一下在放register计算,java的效率估计还不如python呢。
|
d*********g 发帖数: 38 | 13 谢谢keiutou的例子。咱们就follow这个例子聊一下共享,因为我还不是很明白共享的
含义。
“你有一个process,你需要处理一款很大的数据,你就把这个数据没成四块,然后
create四个thread,每个线程都去计算各自的数据,然后把数据汇总到进程中。这个过
程数据从进程到线程,再由线程回进程,就是一个共享的结果”
你说的共享,我理解是指在内存中同一份“很大的数据”,四个线程可以直接访问,而
不需要将各自需要处理的区块再复制到各自的私有栈中。
由你的例子引开,四个线程换成了由四台主机处理,那么每台主机都需要从“很大的数
据”中复制需要处理的区块到该主机。这样每台主机处理的是自己复制的数据,因此没
有共享这一操作。
不知道以上的理解对不对。我是ee做网络的,多线程和os比较薄弱,这段针对这一块再
补。
【在 k*****u 的大作中提到】 : share的好处就是 high performance : 举个例子,如果你的计算机有多个core,比如说四核,那么理论上四个core可以同时进 : 行计算 : 你有一个process,你需要处理一款很大的数据,你就把这个数据没成四块,然后 : create四个thread,每个线程都去计算各自的数据,然后把数据汇总到进程中。这个过 : 程数据从进程到线程,再由线程回进程,就是一个共享的结果 : 当然share的好处不局限于此 : 如果是自己的pc也许只有四核 八核,如果是集群可能就是几十核,几百核,有很多高 : 性能的技术比如openmp(shared memory) openmpi(message passing) hadoop( : mapreduce) 都是类似的进行计算,大同小异
|
z****e 发帖数: 54598 | 14 共享很多时候是不得不共享
如果是硬盘上的共享的话
这个比较容易解决,用db能做很多事情
还有nosql,但是这么做就比较慢,因为涉及io操作
写入硬盘,读的时候从硬盘上读,要先查一下,这些操作都很慢
有些时候,时效要求比较高
比如游戏的pvp,多个client同时联入的话,你需要在短时间内反馈给client
尤其是real time gaming,fps在30左右的话,每一个frame的间隔只有33ms
在33ms内,能做完一次跨网络的传送就不错了,如果加上硬盘的io的话
肯定完不成,所以这个时候就对共享有了较高的要求
你总不可能每一个client自己玩自己的吧?
肯定在server那边需要有一个共享数据的模型
而这个模型一般都放在内存里面
你可以先从斗地主这种游戏开始实现,然后慢慢转换成real time gaming
比如battleship对射,real time的那种
这个时候你就知道多线程和共享几乎是绕不开的
一般的web搞这些也不是完全不可以,但是太吃资源了 |
g*********e 发帖数: 14401 | 15 我说这里的thread obj在heap上
int 在thread里
【在 z****e 的大作中提到】 : 共享很多时候是不得不共享 : 如果是硬盘上的共享的话 : 这个比较容易解决,用db能做很多事情 : 还有nosql,但是这么做就比较慢,因为涉及io操作 : 写入硬盘,读的时候从硬盘上读,要先查一下,这些操作都很慢 : 有些时候,时效要求比较高 : 比如游戏的pvp,多个client同时联入的话,你需要在短时间内反馈给client : 尤其是real time gaming,fps在30左右的话,每一个frame的间隔只有33ms : 在33ms内,能做完一次跨网络的传送就不错了,如果加上硬盘的io的话 : 肯定完不成,所以这个时候就对共享有了较高的要求
|
k****i 发帖数: 101 | 16 public class Main {
static java.util.List list = new java.util.ArrayList<>();
static synchronized void safeAdd() {
unsafeAdd();
}
static void unsafeAdd() {
for(int i = 0; i < 1000000; ++ i) {
list.add(i);
};
}
static void go(Thread t1, Thread t2) throws Exception {
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(list.size());
}
public static void main(String[] args) throws Exception {
go(new Thread(() -> safeAdd()), new Thread(() -> safeAdd()));
list.clear();
go(new Thread(() -> unsafeAdd()), new Thread(() -> unsafeAdd()));
}
}
【在 d*********g 的大作中提到】 : 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。 : 举个栗子: : class M extends Thread{ : int mValue=0; : public void run(){...} : } : class N extends Thread{ : int nValue=1; : public void run{...} : }
|
D**C 发帖数: 6754 | 17 1 不是共享,你开了两个thread,每个thread都有自己的stack,thread里面的local
val 是primtive在stack上。
2 是在main的stack上
你这个例子不好,因为变量都是primative,需要是object才有意义。
【在 d*********g 的大作中提到】 : 最近看java多线程郁闷了,理解不了线程之间共享进程地址空间。 : 举个栗子: : class M extends Thread{ : int mValue=0; : public void run(){...} : } : class N extends Thread{ : int nValue=1; : public void run{...} : }
|
s***a 发帖数: 82 | 18
【在 d*********g 的大作中提到】 : 的确是半路出家,刚开始看多线程,一团雾水,感谢楼上几位。 : 那很多资料都写到“All threads of a process share its virtual address space : and system resources.”或类似的意思,这个share有什么好处呢,既然每个线程都有 : 自己的私有栈。
|
s***a 发帖数: 82 | 19 首先搞清楚什么是虚拟地址空间。
share的好处是协同工作。 比如交易记录要写到共享的数据表里, 如果只是在自己的
stack里做,
别人看不到有啥用呢。
【在 d*********g 的大作中提到】 : 的确是半路出家,刚开始看多线程,一团雾水,感谢楼上几位。 : 那很多资料都写到“All threads of a process share its virtual address space : and system resources.”或类似的意思,这个share有什么好处呢,既然每个线程都有 : 自己的私有栈。
|
k*****u 发帖数: 136 | 20 首先,楼主你如果真想转cs 要看操作系统,数据结构与算法,这两个是最最基本的,
如果还能看看计算机体系结构就更好了。楼主的问题如下,
你说的共享,我理解是指在内存中同一份“很大的数据”,四个线程可以直接访问,而
不需要将各自需要处理的区块再复制到各自的私有栈中。
--> 我没有说过copy,可以直接访问,也可以copy过去,现实中为了防止子线程搞乱主
进程的数据,一般是通过一个函数或者方法读取一块特定的数据,当然理论上你可以直
接访问,这就是为什么说线程是共享资源的
说到这里,你应该听过进程之间的独立资源的。
由你的例子引开,四个线程换成了由四台主机处理,那么每台主机都需要从“很大的数
据”中复制需要处理的区块到该主机。这样每台主机处理的是自己复制的数据,因此没
有共享这一操作。
--> 如果变成四个主机(我当时说道的集群只是举例,大规模数据是怎么被分配处理的
)如果变成四个主机,就是四个独立系统了,这时候进程 线程的都是各自系统的,已
经没有什么共享不共享一说。完全就不是一回事。多线程就指在一个系统中。
如果有时间的话,可以到网上听听online的cs课程 |
|
|
d*********g 发帖数: 38 | 21 感谢keiutou详细而耐心的介绍,真好人也。
操作系统还是躲不掉啊。。。-_-!!!
【在 k*****u 的大作中提到】 : 首先,楼主你如果真想转cs 要看操作系统,数据结构与算法,这两个是最最基本的, : 如果还能看看计算机体系结构就更好了。楼主的问题如下, : 你说的共享,我理解是指在内存中同一份“很大的数据”,四个线程可以直接访问,而 : 不需要将各自需要处理的区块再复制到各自的私有栈中。 : --> 我没有说过copy,可以直接访问,也可以copy过去,现实中为了防止子线程搞乱主 : 进程的数据,一般是通过一个函数或者方法读取一块特定的数据,当然理论上你可以直 : 接访问,这就是为什么说线程是共享资源的 : 说到这里,你应该听过进程之间的独立资源的。 : 由你的例子引开,四个线程换成了由四台主机处理,那么每台主机都需要从“很大的数 : 据”中复制需要处理的区块到该主机。这样每台主机处理的是自己复制的数据,因此没
|
z****e 发帖数: 54598 | 22 楼主目测没有搞懂什么是thread
先理解一下thread
这个跟os没啥关系,虽然java的thread只是os的一层wrapper
但是不懂os也没有什么关系
java所有的program,在启动的时候,会马上启动一个thread
至少一个,这个就是main thread,就是你的main运行的thread
然后其他的thread,如果你启动的话,就会再启动threads
你可以用thread dump看一下你的程序到底运行了多少个threads
然后每个thread有自己的stack,heap部分是共用的
楼主还是要理解java对象以及primitive type两个内存中存放方式的不同
感觉这些跟os没太大关系,虽然os每个人都上过
但是时间一久,不用早就还给老师了
我知道的文科生不懂os一样学java学得好好的
java的多线程是comp101的东西,不用搞那么复杂 |
z****e 发帖数: 54598 | 23 一个program理论上就只有一个process
尤其是可以开多个threads的program
一个process可以运行多个threads
然后每一个thread有自己的stack
但是object并不仅仅是放在stack中
object有两个部分,主体存放在heap里面
然后heap里面的地址,放在stack中
这就是java中的reference
每个thread保留的是object的reference
每次访问的时候,取出reference然后再去heap中把数据读出来
但是有例外,primitive type,比如int, char, boolean这些数据
是直接存放在stack上的,而不是存地址/引用
所以每次用int的时候,不需要访问heap
比如下图中的alphabet,就直接放在stack上了
这就是为啥别人说这个例子看不出来的缘故
你需要object,只有object可以被共享,如果不是object的话
每个thread用到的primitive type都是自己stack上的
楼主是java没学好,不是os的问题
java认认真真从reference, heap, stack这些开始学
到这里应该不是问题,heap, stack这是初学java时候就开始学的
目测楼主没经过这一步,老用ee那一套来思考,那就相当于从怎么造jvm开始搞
那这样一来,你这个路就走错了,jvm很难,而且也没有必要
忘掉你的ee吧,从java基础概念开始搞,否则java会变得很困难
这也是为什么很多ee转行的学得反而不如生物转行的原因
因为生物转行的不会用这一套底层的思维去思考问题
一张白纸,反而容易写,ee转行的老要解释很多底层的东西
那jvm又不是每个人都造过,很多东西就很难解释清楚 |
c*********e 发帖数: 16335 | 24 那volatile boolean呢,为什么就能每个thread都能看到?每次一个thread里的
volatile boolean变量的值变了,其它所有的thread的这个变量的值也跟着变吗?怎么
保证volatile变量的可见性的呢?
【在 z****e 的大作中提到】 : 一个program理论上就只有一个process : 尤其是可以开多个threads的program : 一个process可以运行多个threads : 然后每一个thread有自己的stack : 但是object并不仅仅是放在stack中 : object有两个部分,主体存放在heap里面 : 然后heap里面的地址,放在stack中 : 这就是java中的reference : 每个thread保留的是object的reference : 每次访问的时候,取出reference然后再去heap中把数据读出来
|
z****e 发帖数: 54598 | 25
volatile是强制每次都去取一次value,对于所有thread都可见
如果你知道怎么造jvm的话,你就放心地用
如果不知道的话,就老老实实用synchronized关键字
或者干脆就用java.util, spring, vert.x那些
表没事找事,volatile很早以前就不被推荐使用了
【在 c*********e 的大作中提到】 : 那volatile boolean呢,为什么就能每个thread都能看到?每次一个thread里的 : volatile boolean变量的值变了,其它所有的thread的这个变量的值也跟着变吗?怎么 : 保证volatile变量的可见性的呢?
|
c*********e 发帖数: 16335 | 26 瞎说,volatile还是有用的,关键是看你怎么用。
【在 z****e 的大作中提到】 : : volatile是强制每次都去取一次value,对于所有thread都可见 : 如果你知道怎么造jvm的话,你就放心地用 : 如果不知道的话,就老老实实用synchronized关键字 : 或者干脆就用java.util, spring, vert.x那些 : 表没事找事,volatile很早以前就不被推荐使用了
|
z****e 发帖数: 54598 | 27
在任何时候,volatile都可以不用,就像你自己手写thread一样
早就没人这么用了,你自己跟不上时代就别说别人瞎说
【在 c*********e 的大作中提到】 : 瞎说,volatile还是有用的,关键是看你怎么用。
|
c*********e 发帖数: 16335 | 28 你把自己的跟上时代的java multi-threading code贴出来让大家看看。
【在 z****e 的大作中提到】 : : 在任何时候,volatile都可以不用,就像你自己手写thread一样 : 早就没人这么用了,你自己跟不上时代就别说别人瞎说
|
z****e 发帖数: 54598 | 29
util.concurrent, spring,vert.x都是对付多线程的,说了几万遍了,你不听谁有办法
你能不能不要再让我重复这些说过的话,很烦诶
【在 c*********e 的大作中提到】 : 你把自己的跟上时代的java multi-threading code贴出来让大家看看。
|
c*********e 发帖数: 16335 | 30 vert.x在袋鼠国非常流行吗?
办法
【在 z****e 的大作中提到】 : : util.concurrent, spring,vert.x都是对付多线程的,说了几万遍了,你不听谁有办法 : 你能不能不要再让我重复这些说过的话,很烦诶
|
|
|
z****e 发帖数: 54598 | 31
说了很多遍了,你不识货
我要是告诉你这个东西在欧洲很流行
你是不是就觉得高大上了起来?
【在 c*********e 的大作中提到】 : vert.x在袋鼠国非常流行吗? : : 办法
|