1. 什么是进程, 什么是线程?
进程是资源分配的最小单位。 通常进程的资源都是相互隔离的, 即一个进程没法访问另外一个进程的资源。 这个应该是在操作系统层面对进程访问内存地址做了限制处理。
线程是操作系统调度的基本单位。同一个进程内的所有线程共享进程内的内存资源。
2. 同步(Synchronous)和异步(Asynchronous), 阻塞( Blocking ) 和 非阻塞( Nonblocking)
参考这篇文章, 写的很好
https://blog.youkuaiyun.com/lengxiao1993/article/details/78154467
3. 并发(Concurrency)和并行(Parallelism)
并发:在一个时间段内,多件事情在这个时间段内交替执行。
并行:多件事情在同一个时刻同事发生。多核CPU才能实现并行
如果系统内只有一个CPU,而使用多进程或者多线程任务,那么真实环境中这些任务不可能是真实并行的,毕竟一个CPU一次只能执行一条指令,在这种情况下多进程或者多线程就是并发的,而不是并行的(操作系统会不停地切换多任务)。
临界区
临界区用来表示一种公共资源或者说共享数据,可以被多个线程使用,但是每一次只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源就必须等待。
死锁(Deadlock)、饥饿(Starvation)
死锁:线程1占用锁定A对象,再请求锁定B对象,另一个线程2锁定B对象, 再请求锁定A对象。 这样就会导致死锁。对于线程1来说,由于B对象被线程2锁定,就被阻塞了,对于线程2同样如此, 这样就导致两个线程永远无法执行完成。
饥饿:指某一个或者多个线程因为种种原因无法获得所要的资源,导致一直无法执行
死锁的例子:
package com.example.demo.concurrent;
import java.util.concurrent.*;
public class DeadLock {
private static Object lock1 = new Object();
private static Object lock2 = new Object();
private static ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
Thread thread1 = new Thread(new Run1());
Thread thread2 = new Thread(new Run2());
thread1.start();
thread2.start();
}
static class Run1 implements Runnable {
@Override
public void run() {
synchronized (lock1){ //请求锁定lock1
System.out.println("Run1: execute Run1");
try {
Thread.sleep(10); //确保线程都启动
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){ //请求锁定lock2
System.out.println("Run1: obtained lock2");
}
}
}
}
static class Run2 implements Runnable {
@Override
public void run() {