进程:可并发执行的程序在一个数据集合上的运行过程。

线程:比进程更小的能独立运行的基本单位。   
   
  一个进程通常对应于一个程序(但程序是一个静态的概念,进程是动态的)。而一个进程可以由多个不同的线程做成!     
 
      进程为一个数据结构及能在其上进行的一次操作,它有两个基本特征,一个是进程是可用有资源的独立单位,第二个是进程同时又是一个可以独立调度和分派的基本单位,这两个基本属性使之能够独立运行,也能够并发运行。但是在并发运行的时候,系统还需要执行一系列操作:1、需要创建进程,并为之分配其所必需的资源。2、撤销进程,对资源进行回收。3、进程切换,它需要保留当前进程的CPU环境和设置新选中进程的CPU环境,为此需要花费不少处理时间。正因为进程拥有资源,所以在并发执行进程的时候,在创建、撤销和切换种,系统需要付出较大的开销,因此,系统中设置的进程不能太多,进程切换的频率也不能过高,这就限制了并发程度的提高。   
      线程是进程中的一个实体,它的基本思想是将程序的执行和资源分开,只拥有一点必不可少的资源。一个进程可用有多个线程,但它可以和同属于同一进程的其他线程共享进程所拥有的所有的资源,同一进程中的线程之间可以并发执行。这样的话,并发程度可以获得显著的提高。线程也具有许多进程所具有的特征,因此被称为轻型进程。



---------------------------------------------------------------------------------------------------
Class Test extends Thread{
    private Thread t1 = new Thread() {
        public void run() {
            ...
        }
    }
    private Thread t2 = new Thread() {
        public void run() {
            ...
        }
    } 

  public void start() {
      t1.start();
      t2.start();
  }
  public void run() {
      while(true) {
         
      }      
  }


}

当对象Test的一个Thread进入运行时候,其他Thread处于等待状态所以锁对象(Test),不是锁Thread(t1,t2)



    sleep()方法,是Thread的方法,是使线程停止一段时间的方法。在sleep   时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级,(b)正在运行的线程因为其它原因而阻塞。       
    
  wait()方法,是Object的方法,是线程交互时,如果线程对一个同步对象x   发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。       

wait()/notify():调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。


synchronized和wait()、notify()的关系
:

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。





一个程序调用fork函数,系统为一个新的进程准备了数据段,堆栈段,代码段,
首先,新进程与旧进程使用同一个代码段,因为它们的程序是相同的,
对于数据段和堆栈段,系统则复制一份给新的进程,
这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,
虽然它继承了父进程的一切数据,但实际上数据却已经分开,
相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。
两个进程要共享数据的话,只能使用共享内存与消息队列等来操作。

如果数据段和堆栈都很大,一次fork就要复制一次,那么fork的开销岂不是很大?
其实一般CPU都是以“页”为单位分配空间的,
fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,
实际执行fork时,物理空间上两个进程的绝大部分数据段和堆栈段都还是共享着的,
只有一个进程写了某个数据时,这时两个进程之间的数据才有了区别,
系统只将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。

要方便的使用共享变量,最好使用线程方式,但是需要考虑变量的保护问题,而
使用进程的共享内存与消息队列,就不需要用户来保护变量,因为它们已经提供了
保护。