1.并发编程的优缺点?
优点:
- 充分利用多核CPU的计算能力,通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升;
- 方便业务拆分,提升系统并发能力和性能;
缺点:
- 内存泄漏;
- 线程安全问题;
- 复杂程度增加:比如死锁;
- 资源消耗增加:比如频繁的上下文切换也可能导致额外的性能开销;
2.并发编程三要素?
- 原子性:原子,就是一个不可再被分割的颗粒。原子性就是指一个或多个操作要么全部执行成功要么全部执行失败;
- 可见性:一个线程对共享变量的修改,另一个线程能够立刻看到;
- 有序性:程序执行的顺序按照代码先后顺序执行。(处理器可能会对指令进行重排序)
3.什么叫指令重排?
指令重排(也称为指令重排序)是指在程序执行过程中,指令的执行顺序可能与它们在代码中的顺序不一致的现象。编译器和处理器为了提高程序的执行效率,可能会根据一些规则和优化策略对指令进行重新排序。但是,这种重排序必须保证最终的执行结果与不进行重排时的执行结果保持一致,以确保程序的正确性;存在数据依赖关系的也不允许指令重排
指令重排主要是基于处理器的特性,如多级缓存、多核等,来优化指令的执行顺序。这种优化可以使程序在保证业务运行的同时,充分利用CPU的资源,发挥最大的性能。然而,指令重排也可能会导致线程安全问题,特别是在多线程环境下。因此,在编写并发程序时,需要特别注意指令重排的影响,并采取相应的措施来确保程序的正确性和性能。
4.如何避免指令重排?
- 使用volatile关键字:在Java中,volatile关键字可以确保多线程环境下变量的可见性和有序性。当一个变量被声明为volatile时,它会禁止指令重排,确保所有线程看到的变量值都是一致的。volatile关键字还可以防止JVM的指令重排优化,确保代码的执行顺序与预期一致。
- 使用synchronized关键字:synchronized关键字可以用来保证代码块或方法的原子性,即在同一时刻只能有一个线程执行被保护的代码。通过synchronized块或方法,可以确保指令按照预期的顺序执行,避免指令重排导致的线程安全问题。
- 使用Lock接口及其实现类:Java中的Lock接口及其实现类(如ReentrantLock)也可以用来控制并发访问,保证代码的正确执行顺序。与synchronized相比,Lock接口提供了更灵活的控制方式,可以更好地避免指令重排带来的问题。
- 避免使用final关键字修饰引用类型变量:在Java中,final关键字修饰的引用类型变量在初始化后不能被改变。但是,如果final变量指向的对象是可变的,那么其他线程仍然可以修改该对象的内容。因此,在使用final关键字时,需要特别注意避免指令重排导致的线程安全问题。
- 了解并遵循Happens-Before规则:Happens-Before规则是Java内存模型定义的一组规则,用于确定多线程环境中哪些操作是有序的。遵循这些规则可以确保指令按照预期的顺序执行,避免指令重排导致的线程安全问题。
5.并发?并行?串行?
- 并发:多个任务在同一个cpu上,按细分的时间片轮流执行,从逻辑上来看那些任务是同事执行的;(两个队列一台咖啡机)
- 并行:单位时间内,多个处理器或多核处理器同时处理多个任务,是真正意义上的同时进行;(两个队列一两台咖啡机)
- 串行:有n个任务,由一个线程按顺序执行,犹豫任务,方法都在一个线程执行,所以不存在线程不安全情况,也就不存在临界区的问题;(一个队列一台咖啡机)
6.线程和进程的概念和区别?
进程:是操作系统资源分配的基本单位,一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程。
线程:处理器任务调度和执行的基本单位,又叫做轻型进程;进程中的一个执行任务,负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据;
区别: