【问题标题】:Difference between process and thread进程和线程的区别
【发布时间】:2011-04-21 20:42:21
【问题描述】:

今天面试时被问到一个问题。首先他们问如何提供同步 线程之间。然后他们问如何提供进程之间的同步,因为我告诉他们,每个进程内部的变量不能与其他进程共享,所以他们要求我解释两个进程如何相互通信以及如何提供同步 它们之间,以及在哪里声明共享变量?现在面试结束了,但我想知道答案,谁能解释一下?谢谢。

【问题讨论】:

  • 共享等待,例如命名的 Mutex 或 Semaphore,将在整个进程中同步调用。
  • 真正的进程间通信高度依赖于平台。通常,您可以通过进程之间的网络套接字进行通信来避免这种情况。我个人很想从商业方面给出有点圆滑但高度正确的答案“购买兵马俑许可证”。 :)
  • ok,例如 Mutex 或 Semaphore,所以这意味着我们需要一个 semaphore 变量,以便这些进程可以访问它并检查它。那么在哪里申报呢?每个进程内部?
  • 小心:Java 中不直接支持跨进程互斥锁和信号量。 Java Semaphore 类是一个纯进程内工具。更一般地说,大多数操作系统都为跨进程同步提供了信号量机制,但这并不容易从 Java 代码中访问。
  • 我认为这个问题的重点是:这个问题是关于 Java 的,还是关于更一般的机制的?

标签: java multithreading process


【解决方案1】:

我认为面试官可能没有使用正确的术语。进程在自己的空间中运行,并且在单独的答案中已提到,您必须使用特定于操作系统的机制在进程之间进行通信。这称为进程间通信的 IPC。

使用套接字是一种常见的做法,但可能效率极低,具体取决于您的应用程序。但如果使用纯 Java,这可能是唯一的选择,因为普遍支持套接字。

共享内存是另一种技术,但它是特定于操作系统的并且需要特定于操作系统的调用。您必须使用 JNI 之类的东西让 Java 应用程序访问共享内存服务。共享内存访问不同步,因此您可能必须使用信号量来同步多个进程之间的访问。

类 Unix 系统提供多种 IPC 机制,使用哪一种取决于您的应用程序的性质。共享内存可能是一种有限的资源,因此它可能不是最好的方法。谷歌搜索此主题会提供大量点击,提供有关技术细节的有用信息。

【讨论】:

    【解决方案2】:

    进程是虚拟内存空间、代码、数据和系统资源的集合。线程是要在进程中串行执行的代码。处理器执行线程,而不是进程,因此每个应用程序至少有一个进程,而一个进程总是至少有一个执行线程,称为主线程。除了主线程之外,一个进程还可以有多个线程。在引入多线程执行之前,应用程序都被设计为在单个执行线程上运行。

    当一个线程开始执行时,它会继续执行,直到它被杀死或被具有更高优先级的线程(由用户操作或内核的线程调度程序)中断。每个线程可以运行单独的代码段,或者多个线程可以执行同一段代码。执行相同代码块的线程维护不同的堆栈。进程中的每个线程共享该进程的全局变量和资源。

    【讨论】:

      【解决方案3】:

      要在两个进程之间进行通信,我想您可以使用 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 相互通信。但他们不满意。他们一遍又一遍地重复这个问题,所以还有其他想法吗?
      • 但是请注意,操作系统有时会禁止来自不同进程或用户的第二次绑定到同一端口。
      • @Piotr 谢谢你。我很快就把它放在一起,但我确信会有特定于操作系统的问题需要解决。 @ratzip我假设您的意思是在两个单独的进程上运行的两个单独的JVM。如果是这种情况,它们将共享相同的内存(显然是虚拟的),但都没有指向彼此内存的指针。因此,您无法在单独的进程下同步对象。当他们说您不能使用 Sockets 和 IO 时,他们是否在寻找特定的东西?
      • 他们询问两个进程如何相互通信和同步。这就是问题。我可能通过两个进程可以像线程一样同步。所以我告诉他们一个进程等待另一个 put 值到一个公共变量,然后它可以获取它。所以他们问在哪里声明公共变量,因为该变量不能被进程共享?
      • 他们可能一直在寻找一些非常具体的东西,但一般来说。两个进程无法在共享内存块上同步,您可以在 java 代码中看到,例如 synchronize(myObject){ ... }。两个进程不知道彼此的堆,并反过来引用虚拟内存。
      【解决方案4】:

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

      【讨论】:

      • 是的,我明白你的回答,进程不共享任何状态,但我想知道两个进程是否会访问同一个共享内存?在这种情况下,我们是否应该考虑同步?
      【解决方案5】:

      从系统的角度来看,一个线程是由他的“state”和“instruction pointer”定义的。

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

      线程“state”可以是:寄存器(eax、ebx等)、信号open文件代码堆栈、由该线程管理的数据(变量、数组等)以及堆。

      进程是一组线程,它们共享一部分“状态”:可能是代码数据。 希望我能回答你的问题;)

      编辑: 进程可以通过 IPC(进程间通信)进行通信。有 3 种机制:共享内存消息队列。我可以使用 Semaphors

      实现进程之间的同步

      我可以使用互斥锁pthread_mutex_lock、pthread_mutex_unlock 等)进行线程同步

      【讨论】:

      • 好的,谢谢。但我的问题是两个进程如何相互通信?是否存在这种情况:两个进程访问共享内存?如果是,如何提供同步?
      • 我向他们解释生产者和消费者的问题,使用锁,信号量,但是他们问如何提供进程之间的同步,我回答他们声明一个公共变量,所以他们问因为每个进程中的变量可以不与他人共享,那么在哪里声明公共变量?
      • 请注意,您的寄存器名称(eip、eax、ebx)是系统相关的(在您的情况下为 x86),而您的其余答案非常通用。
      • 是的,我知道,但这仅用于示例目的。
      • @ratzip 我之前做过的一件事是在 FPGA 中实现 SMP 之间的同步。我认为这与您的问题非常相似。关键是使用两个处理器都可以访问的“硬件”互斥锁。可以在 SOPC builder 中创建硬件互斥 IP 核。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

          一句话,进程的设计比线程更独立。
          它们的主要区别可以在内存级别进行描述。不同的进程彼此之间不共享任何内容,从寄存器、库存内存到堆内存,这使得它们在各自的轨道上安全。但是,通常线程被设计为共享一个公共堆内存,这为多进程计算任务提供了一种更紧密的连接方式。创建一种更有效的方式来占用计算资源。

          例如如果我用 3 个进程计算,我必须让它们各自完成它们的工作并在系统级别等待它们的结果,同时,寄存器和堆栈内存总是被占用。但是,如果我用 3 个线程来做,那么如果线程 2 幸运地提前完成了它的工作,因为它计算的结果已经存储到公共堆内存池中,我们可以简单地杀死它,而无需等待其他人提供他们的结果,并且释放的寄存器和库存内存资源可以用于其他目的。

          【讨论】:

            【解决方案9】:

            流程:

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

            线程:

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

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

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                猜你喜欢
                • 2016-09-22
                • 2015-06-08
                • 2010-09-17
                • 2011-09-29
                • 2010-10-18
                • 2012-12-18
                相关资源
                最近更新 更多