进程和线程的区别

8
今天在面试中被问到一个问题。他们首先问如何在线程之间提供同步,然后问如何在进程之间提供同步,因为我告诉他们,每个进程内部的变量不能与其他进程共享,所以他们让我解释一下两个进程如何进行通信以及如何提供同步,并且在哪里声明共享变量?现在面试已经结束了,但我想知道答案,请问有人能解释一下吗?谢谢。

一个共享等待,例如命名的Mutex或Semaphore,可以用于在进程之间同步调用。 - vcsjones
真正的进程间通信高度依赖于平台。通常,您可以通过在进程之间使用网络套接字进行通信来避免这种情况。从商业角度来看,我个人会倾向于给出有些轻率但高度正确的答案:“购买Terracotta许可证。” :) - Affe
好的,例如 Mutex 或 Semaphore,这意味着我们需要一个信号量变量,以便这些进程可以访问并检查它。那么在哪里声明它?在每个进程内部吗? - user707549
注意:Java 不直接支持跨进程互斥锁和信号量。Java 的 Semaphore 类是一个纯粹的进程内工具。一般来说,大多数操作系统都提供了用于跨进程同步的信号量机制,但这在 Java 代码中不容易访问。 - Joachim Sauer
我认为这个问题的一个重要点是:这个问题是关于特定的Java还是更一般的机制? - Joachim Sauer
10个回答

6
我认为面试官可能没有使用正确的术语。一个进程在自己的空间中运行,正如先前提到的,在进程之间通信需要使用操作系统特定机制。这被称为IPC(进程间通信)。
使用套接字是一种常见做法,但根据你的应用程序,可能会非常低效。但如果只使用Java,这可能是唯一的选择,因为套接字得到了普遍支持。
共享内存是另一种技术,但这是OS特定的,需要OS特定的调用。对于Java应用程序访问共享内存服务,你需要使用JNI之类的东西。共享内存访问不是同步的,所以你可能需要使用信号量来同步多个进程之间的访问。
类Unix系统提供了多种IPC机制,使用哪种取决于你的应用程序的性质。共享内存可能是有限的资源,因此可能不是最佳方法。在这个主题上进行谷歌搜索可以提供大量有用的技术细节信息。

3
一个进程是一组虚拟内存空间、代码、数据和系统资源。线程是在进程内串行执行的代码。处理器执行线程而非进程,因此每个应用程序至少有一个进程,并且一个进程始终有至少一个执行线程(称为主线程)。进程可以有多个线程,除了主线程之外。在引入多个执行线程之前,所有应用程序都设计为在单个执行线程上运行。
当线程开始执行时,它会一直执行,直到被杀死或被具有更高优先级的线程中断(由用户操作或内核的线程调度程序)。每个线程可以运行单独的代码段,或者多个线程可以执行相同的代码段。执行相同代码块的线程维护单独的堆栈。进程中的每个线程共享该进程的全局变量和资源。

2

为了在两个进程之间进行通信,我建议您使用ServerSocket和Socket来管理进程同步。您可以绑定到特定的端口(获取锁),如果已经有一个进程绑定了该端口,则可以连接到该套接字(阻塞)并等待服务器套接字关闭。

private static int KNOWN_PORT = 11000;//arbitrary valid port
private ServerSocket socket;
public void acquireProcessLock(){
   socket = new ServetSocket(KNOWN_PORT);
   INetAddress localhostInetAddres = ...
   try{
      socket.bind(localhostInetAddres );
   }catch(IOException failed){
      try{
       Socket socket = new Socket(localhostInetAddres ,KNOWN_PORT);
       socket.getInputStream().read();//block
      }catch(IOException ex){ acquireProcessLock(); } //other process invoked releaseProcessLock()
   }
}
public void releaseProcessLock(){
  socket.close();
}

不确定这是否是实际最佳方法,但我认为值得考虑。


我也用Socket进行了通信来回答他们的问题。但是他们并不满意。而且他们一遍又一遍地重复着同样的问题,那么还有其他想法吗? - user707549
请注意,操作系统有时会禁止不同进程或用户对同一端口进行第二次绑定。 - Piotr Findeisen
@Piotr 谢谢你。我是匆忙组合的,但我相信会有 OS 特定问题需要解决。@ratzip 我假设您指的是在两个独立进程上运行的两个单独的 JVM。如果是这种情况,它们将共享相同的内存(显然是虚拟的),但是彼此都没有指针。因此,您无法在独立进程下同步对象。当他们说您不能使用 Sockets 和 IO 时,他们是否正在寻找特定的东西? - John Vint
他们问如何使两个进程之间进行通信并实现同步。这就是问题所在。我认为可以像线程一样同步两个进程。因此,我告诉他们一个进程等待另一个进程将值放入共享变量中,然后它可以获取该值。所以他们问在哪里声明共享变量,因为变量不能被进程共享? - user707549
他们可能一直在寻找某些特定的东西,但总的来说,在Java代码中,两个进程不能在共享内存上同步,你会看到像synchronize(myObject){ ... }这样的代码。两个进程不知道彼此的堆,并且反过来引用虚拟内存。 - John Vint

1

同步仅适用于Java中的线程,而不适用于进程。它们在跨进程工作时没有任何效用,因为进程不共享需要同步的状态。一个进程中的变量与另一个进程中的变量不会具有相同的数据。


是的,我理解你的回答,这些进程不共享任何状态,但我想知道两个进程是否会访问同一块共享内存?如果是这样,我们需要考虑同步吗? - user707549

1

从系统角度来看,线程由其"状态"和"指令指针"定义。

指令指针(eip)包含下一条要执行的指令的地址。

线程的"状态"可以是:寄存器(eax、ebx等)、信号、打开的文件、代码、堆栈、由该线程管理的数据(变量、数组等)以及堆。

进程是一组共享部分"状态"的线程:它可能是代码、数据、堆。

编辑: 进程可以通过IPC(进程间通信)进行通信。有3种机制:共享内存消息队列。进程之间的同步可以使用信号量进行。

线程同步可以使用互斥锁pthread_mutex_lock,pthread_mutex_unlock等)来实现


是的,谢谢。但我的问题是两个进程如何相互通信?并且是否存在这种情况:两个进程访问共享内存?如果是这样,如何提供同步? - user707549
我向他们解释了生产者和消费者问题,使用锁、信号量,但他们问如何在进程之间提供同步,我回答说声明一个公共变量,于是他们问既然每个进程中的变量不能与其他进程共享,那么在哪里声明公共变量? - user707549
请注意,您的寄存器名称(eip、eax、ebx)是与系统相关的(在您的情况下是x86),而您的其余答案则是相当通用的。 - Joachim Sauer
是的,我知道,但那只是为了举例而已。 - Dimitri
@ratzip 我以前做过的一件事是在 FPGA 中实现 SMPs 之间的同步。我认为这与你的问题非常相似。关键是使用一个“硬件”互斥锁,可以由两个处理器访问。在 SOPC builder 中可以创建一个硬件互斥锁 IP 核。 - Hao Shen

0

请查看Terracotta Cluster或Terracotta的DSO Clustering文档,了解如何解决此问题(字节码操作,维护Java语言规范在putfield/getfield级别上的语义等)。


0

简单来说,进程比线程更独立。
它们的主要区别在于内存层面。不同的进程之间没有任何共享,从寄存器、栈内存到堆内存,这使得它们各自安全地运行。然而,通常线程被设计为共享一个公共的堆内存,这为多个进程计算任务提供了更紧密的连接方式。创造了一种更有效的占用计算资源的方式。

例如,如果我使用3个进程进行计算,我必须让它们每个人完成工作并在系统级别等待其结果,同时,寄存器和栈内存总是被占用。然而,如果我使用3个线程,则如果线程2幸运地更早地完成其工作,因为它计算出的结果已经存储在公共堆内存池中,我们可以简单地杀死它,而不必等待其他线程交付其结果,这样释放的寄存器和栈内存资源可以用于其他目的。


0

最简单的答案是,进程意味着正在执行的程序,而程序只是函数的集合。 线程是进程的一部分,因为所有线程都是函数。 换句话说,一个进程可以有多个线程。 操作系统总是为进程分配内存,并将该内存分配给该进程的线程。操作系统不会为线程分配内存。


-1

进程:

  • 进程就是正在执行的程序。
  • 每个进程都有自己的内存地址空间。
  • 进程用于重量级任务,即基本上是应用程序的执行。
  • 进程之间通信的成本很高。
  • 从一个进程切换到另一个进程需要一些时间来保存和加载寄存器、内存映射等。
  • 进程是操作系统的方法。

线程:

  • 线程是轻量级的子进程。
  • 线程共享相同的地址空间。
  • 线程之间通信的成本较低。

注意:每个线程至少需要一个进程。


-2

我想进程可以通过第三方方式进行通信:文件或数据库...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接