1.进程是操作系统中资源分配的最小单位;线程是cpu调度的最小单位
--操作系统不直接给线程分配资源,线程使用的是进程的资源
--cpu调度时,调度的是进程内的线程
--线程被包含在进程中,是进程中的实际运作单位
--一条线程是进程中一条单一顺序的控制流,一个进程中可以并行多条线程执行不同的任务
2.进程有独立的地址空间;同一个进程内的线程共享当前进程的数据和地址空间;
--地址空间 是一种抽象的概念;每个进程都有自己独立的地址空间;他是进程与外部世界隔离的一种机制,别的进程不能访问或篡改当前进程内的数据和代码
3.高并发编程时可以选择多进程和多线程;多进程并发时,内存相互独立,通信的时候需要使用管道、消息队列、共享内存等 ;多线程共享进程的内存,线程间的通信更方便;进程的销毁需要释放内存空间
4.一个进程内可以创建多少个线程呢?32位操作系统用户态的虚拟内存空间假设有3G ,一个线程最少需要10M 那理论上可以创建300个线程;64位操作系统用户态的虚拟内存有128TB,可以创建无限个线程;需要操作系统的其他限制控制
5.进程上下文切换 涉及 地址空间、寄存器、打开的文件描述符 等信息的保存和恢复;
线程上下文切换,因为线程共享了地址空间和大部分资源;所以只需要保存和恢复部分寄存器信息
性能开销更小
6.如果要模拟CPU打满,需要使用多进程,创建和cpu个数相等个数的多进程,每个进程执行死循环永不停止
def cpu_bound():
while True:
pass
if __name__ == '__main__':
# 创建多进程 有几个cpu 就创建几个进程 进程执行函数可以实现将cpu打满
num_cores = multiprocessing.cpu_count()
processes = []
for i in range(num_cores):
p = multiprocessing.Process(target=cpu_bound)
p.start()
processes.append(p)
print("主进程等待子进程结束")
for p in processes:
p.join()
print("主进程结束")
JVM进程、线程和操作系统中的进程、线程的关系
1.JVM从程序入口main方法启动后,就有了一个JVM进程,main方法是主线程;jvm中没有多进程编程,只有多线程编程;多线程使用synchronization等进行并发控制
2.java1.2之前 线程使用的是绿色线程,由jvm虚拟机调度,和操作系统无关;但由于和原生线程相比限制较多;在java1.2之后开始使用native thread,本质上就是操作系统中的线程
3.java线程有6种状态
BLOCKED 多个线程在等待synchronized同步资源时 等待
WAITING 线程的执行流程中调用了如Object.wait()
等方法而进入等待状态
TIMED_WAITING 线程的执行流程中调用了如Thread.sleep(1)
等方法而进入限时等待状态
操作系统线程有3种状态
java中多线程编程,共享资源同步控制的解决法案
synchronized | 作用在方法或代码块中;同一时刻只有一个线程访问共享资源,其他线程将被阻塞,直到当前线程执行完毕并释放锁 | synchronized 锁住的对象必须是全局共享的对象;否则锁住的不是一个对象,同步控制不生效 |
AtomicInteger | 原子变量 处理整数类型的数据 可以处理单个整型变量操作的场景 如计数器 序列号生成等 | 如果涉及到复杂的复合运算或者需要保证多个变量的一致性 就需要结合synchronized 确保数据的完整性和一致性 |
volatile | 一个变量被volatile修饰时,每次修改该变量都直接从主存修改,而不是线程私有的本地内存,确保所有线程看到的内容是一样的 可以处理单个变量的可见性 | |
ReentrantLock | 比synchronized更灵活 | 互斥 可重入 可设置为公平锁 |
package com.company.thread;
public class Printtask implements Runnable {
// 锁对象也必须是全局的静态变量 否则不是一个锁对象 也不能控制并发
private static Object lock = new Object();
// 共享变量必须是类级别的变量 因为他们可以在所有实例对象之间共享,并且只有一份副本存在于内存中
private static int count = 1;
private String name;
Printtask(String name) {
this.name = name;
}
@Override
public void run() {
synchronized (lock) {
System.out.println(name + "正在打印:");
try {
// 让线程休眠一段时间,模拟打印过程
count++;
Thread.sleep(10);
count--;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Printtask("aaaa"));
Thread t2 = new Thread(new Printtask("bbbb"));
Thread t3 = new Thread(new Printtask("cccc"));
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
}
参考文档: