我删除了旧问题,因为这是一个更清楚的问题。 如果在多核CPU上启动任何java进程,那么这个java进程将分配给哪个核心?这个操作系统特定吗?如果java进程启动了很多线程,那么其他内核是否有机会运行这些线程,或者只有启动了java进程的核心才能处理这些线程?
寻找建设性的答案。
答案 0 :(得分:0)
如果任何操作系统是多处理器,那么JVM会使用所有操作系统还是其中一个?
在大多数现代硬件架构中,JVM将使用操作系统提供给它的所有CPU /核心。
呃,不是吗?我不确定你在这里问什么,但并发的整个问题是CPU有自己的缓存。这就是内存同步和锁定如此重要的原因。线程可能会对其缓存内存进行本地更改,或者由于其他线程对中央存储所做的更改,其缓存内存可能会失效。所以当然存在多处理器和不同内存“上下文”的“并发问题”。由于处理器有不同的内存上下文,所以它们对应的内存线程也会有不同的内存上下文,所以它们不会出现并发问题?
编辑:
以下是我的主要疑点:如果JVM使用了4个进程(P1,P2,P3,P4),那么在一个进程下运行的线程将面临并发问题,P1下的线程T1和P2下的线程T2永远不会有并发问题,因为它们有不同的内存上下文。我是对还是错?
你错了。 JVM将在4个处理器上调度您的4个用户线程和其他后台线程(gc,finalizer,jmx等),与同一操作系统上运行的其他进程争用。在某个时间点,JVM可能正在使用所有4个处理器,或者可能不使用处理器,具体取决于操作系统上运行的其他进程。
如果T1和T2在不同的处理器上,那么它们可以同时运行。除非共享数据,否则所有线程都不会出现并发问题。如果T1对T2正在使用的对象进行更改,则T2可能会也可能不会看到这些更改,具体取决于正在使用的同步。这种内存同步是多线程编程的一个大问题。例如:
static Integer sharedValue = 1;
...
// thread T1 changes the shared value
sharedValue = 2;
...
// thread T2 reads the shared value later
// it is unknown whether this will print 1 or 2
System.out.println("shared = " + sharedValue);
如果T2换出并且T3在同一处理器上运行,实际上可能会出现较少的并发问题,因为它们都使用相同的CPU缓存,但您仍然需要担心锁定< / em>的。例如,如果T2任务执行的++
似乎是原子的,但实际上是3个操作(get,increment,store),它可能会在增量之后但在存储之前被中断并且可能会覆盖T3的增量:
static int counter = 0;
...
// thread T2
// 3 operations: get, increment, store
// this thread might be interrupted in the middle causing a ++ to be lost
counter++;
...
// thread T3
// 3 operations: get, increment, store
// this thread might be interrupted in the middle causing a ++ to be lost
counter++;
...
// later on, even if T2 and T3 have completed, you may see the counter as 1 or 2
System.out.println("counter = " + counter);
因此,无论您的线程是在多个还是单个处理器系统上运行,锁定都是一个问题。请点击此处查看better example of non-atomic operations。
答案 1 :(得分:0)
听起来你需要理解线程和 parallelism 之间的区别。
线程是一个执行原语,其中指令在CPU上运行
并行性是多个线程同时执行的可能性
作为实现细节,JVM为内部目的运行多个线程。例如,垃圾收集器在与代码不同的线程上运行。同样,您使用的代码和库可能会产生任意数量的线程作为其自身实现的一部分。是否将并行运行是另一回事。
操作系统负责为线程分配CPU核心,以便它们可以运行,这些最终会限制程序的潜在并行性。
是的,并发问题确实存在,因为线程本质上是邪恶的。
答案 2 :(得分:0)
如果任何操作系统是多处理器,那么JVM会使用所有操作系统还是其中一个?
JVM将使用与操作系统允许的内核一样多的内核...最多可运行线程数。
我问这个是因为在一个处理器中,一次只能运行一个线程,所以如果有4个处理器,那么当时会运行4个线程吗?
最多 4个线程可以同时运行。这取决于线程是否可运行,以及操作系统是否准备好在4个内核上调度应用程序的线程。 (系统通常运行其他进程以及JVM。)
由于处理器有不同的内存上下文,所以它们对应的内存线程也会有不同的内存上下文,所以它们不会出现并发问题?
Java中的并发是一个重要主题。我建议您首先阅读Concurrency主题的Java Tutorial部分。
是的......不同的核心将共享相同的地址空间,你是正确的,它们会有不同的“内存上下文”。具体来说,它们不会共享寄存器集,并且它们可能不共享内存第1 /第2 /第3级内存缓存。但是,如果您遵循编写正确的多线程Java代码的规则,那么您应该没有问题。这些规则(在JLS中指定为Java内存模型)清楚地表明多线程程序可以并且不能假设一个线程所做的更改何时对另一个线程可见。
<强>更新强>
以下是我的主要疑点:如果JVM使用了4个进程(P1,P2,P3,P4),那么在一个进程下运行的线程将面临并发问题,P1下的线程T1和P2下的线程T2永远不会有并发问题,因为它们有不同的内存上下文。我是对还是错?
很难知道你的意思,因此很难判断你是“正确”还是“错误”。
然而:
如果您有4个进程,那么每个进程都将运行自己的JVM。每个JVM有一个进程。不多也不少。
每个线程属于一个JVM(因此属于一个进程),并且在正常情况下 1 不能干扰属于另一个JVM的线程。不同的进程不共享内存上下文,除非你做一些事情来实现它。操作系统确保进程地址空间/内存上下文是分开的。 (如果没有,那将是一个重大的安全问题!!)
属于一个JVM 的线程可以相互干扰。他们做共享相同的虚拟地址空间,但内存共享并不完美(参见上面有关缓存等)。
线程到核心的映射是动态的;即它可以改变毫秒。但是,操作系统会确保不同进程中线程之间的内存上下文没有意外泄漏。
1 - 当进程使用“共享内存”段时,图片很复杂。但是,您无法在纯Java中执行此操作,甚至在JVM中的本机代码库中执行此操作也会非常困难。