精华内容
下载资源
问答
  • 有三种方式可以用来创建线程:继承Thread类实现Runnable接口应用程序可以使用Executor框架来创建线程池实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别对象情况下,这...
    b681e683c437824aaa3b90c31c3fcf32.png

    以下几道题目比较初级,是必须要掌握的多线程基础面试题。

    创建线程有几种不同的方式?你喜欢哪一种?为什么?

    有三种方式可以用来创建线程:

    • 继承Thread类
    • 实现Runnable接口
    • 应用程序可以使用Executor框架来创建线程池

    实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。

    概括的解释下线程的几种可用状态。

    新建( new ):新创建了一个线程对象;

    可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取CPU的使用权;

    运行( running ):可运行状态( runnable )的线程获得了CPU时间片( timeslice ) ,执行程序代码;

    阻塞( block ):阻塞状态是指线程因为某种原因放弃了CPU 使用权,也即让出了 CPU timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。

    阻塞的情况分三种:

    1. 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。
    2. 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。
    3. 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。

    死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

    同步方法和同步代码块的区别是什么?

    区别:

    • 同步方法默认用this或者当前类class对象作为锁;
    • 同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;

    在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

    监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。

    java 还提供了显式监视器( Lock )和隐式监视器( synchronized )两种锁方案。

    什么是死锁(deadlock)?

    两个线程或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。

    如何确保N个线程可以访问N个资源同时又不导致死锁?

    多线程产生死锁的四个必要条件:

    • 互斥条件:一个资源每次只能被一个进程使用。
    • 保持和请求条件:一个进程因请求资源而阻塞时,对已获得资源保持不放。
    • 不可剥夺性:进程已获得资源,在未使用完成前,不能被剥夺。
    • 循环等待条件(闭环):若干进程之间形成一种头尾相接的循环等待资源关系。

    只要破坏其中任意一个条件,就可以避免死锁

    一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

    选自:

    https://www.jianshu.com/p/bfbe2858c21f

    展开全文
  • 一.什么是单例以及单例的使用场景就不多说了,不清楚的可以看我上篇文章或者自行查找 二.单例和多并发之间的规则 单例就是只能创建一个实例对象,而多并发...几种常见的单例模式的写法 1.最常规的(线程不安全...

    一.什么是单例以及单例的使用场景就不多说了,不清楚的可以看我上篇文章或者自行查找

    二.单例和多并发之间的规则

         单例就是只能创建一个实例对象,而多并发情况下如果不处理一下单例的写法很难保证只创建一个实例对象,所以后面会出问题

         处理的思路:在创建对象的时候使用同步锁,或者直接懒人做法---放一个静态的实例对象

    三.几种常见的单例模式的写法

        1.最常规的(线程不安全--不支持多并发)

    public class Singleton {
     
        //一个静态的实例
        private static Singleton singleton;
        //私有化构造函数
        private Singleton(){}
        //给出一个公共的静态方法返回一个单一实例
        public static Singleton getInstance(){
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }

       2.上面的常用的是不支持并发的,所以后面考虑在方法上加同步锁,但是如果在上面那个获取对象的方法上加锁则会每次在获取对象时都需要等待,蛮费时间的,所以不能这么玩,

           可以使用如下方法内部类写法(其实我感觉他和饿汉式差不多,都是new一个静态实例放在那里)

    public class Singleton {
    
        /* 私有构造方法,防止被实例化 */
        private Singleton() {
        }
    
        /* 此处使用一个内部类来维护单例 */
        private static class SingletonFactory {
            private static Singleton instance = new Singleton();
        }
    
        /* 获取实例 */
        public static Singleton getInstance() {
            return SingletonFactory.instance;
        }
    
    }
    备注:
    第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,因为JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的
    
    可以对比一下饿汉式写法:
    public class Singleton {
        private static Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton getInstance() {
            return instance; 
        }
    }

     

        3.或者在创建类的那个时刻同步就行,获取对象的方法就不同步(和懒汉式类似,需要时加载就行)

    public class SingletonTest {
     
        private static SingletonTest instance = null;
     
        private SingletonTest() {
        }
     
        private static synchronized void syncInit() {
            if (instance == null) {
                instance = new SingletonTest();
            }
        }
     
        public static SingletonTest getInstance() {
            if (instance == null) {
                syncInit();
            }
            return instance;
        }
    }
    
    懒汉式的不高效写法,相当于也是同步了获取对象的方法
    public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
    if (instance == null) {
    instance = new Singleton();
    }
    return instance;
    }
    }

     

      4.所谓的双重锁写法(相当于变相的在类的创建时加同步锁,和方法三原理类似或者和方法二内部类利用jvm类加载机制类似)

    public class Singleton{
        private volatile static Singleton singleton;
        private Singleton(){}
        public static Singleton getSingleton(){
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }

     

    转载于:https://www.cnblogs.com/feichen-66/p/11195818.html

    展开全文
  • 文章目录多线程进程和线程区别是什么?*创建线程几种不同方式?你喜欢一种?为什么?...有三种方式可以用来创建线程: 继承Thread类 实现Runnable接口 应用程序可以使用Executor框架来创建

    多线程

    1.进程和线程的区别是什么?

    进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

    2.*创建线程有几种不同的方式?你喜欢哪一种?为什么?

    有三种方式可以用来创建线程:

    • 继承Thread类
    • 实现Runnable接口
    • 应用程序可以使用Executor框架来创建线程池
      实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。

    3.概况的解释下线程的几种可用状态

    线程在执行过程中,可以处于下面几种状态:

    • 就绪(Runnable):线程准备运行,不一定立马就能开始执行。
    • 运行中(Running):进程正在执行线程的代码。
    • 等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
    • 睡眠中(Sleeping):线程被强制睡眠。
    • I/O阻塞(Blocked on I/O):等待I/O操作完成。
    • 同步阻塞(Blocked on Synchronization):等待获取锁。
    • 死亡(Dead):线程完成了执行。

    4.同步方法和同步代码块的区别是什么?

    在Java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。

    5.请你谈谈关于Synchronized和Lock

    synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。JDK1.5以后引入了自旋锁,锁粗化,轻量级锁,偏向锁来有优化关键字的性能。
    Lock是一个接口,而synchronizaed是Java中的关键字,synchronized是内置的语言实现;synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象的发生;而Lock在发生异常时,如果没有主动通过unlock()去释放锁。则很可能造成死锁现象,因此使用Lock时需要在finally代码块中释放锁,Lock可以让等待锁的线程响应中断,而synchronize却不行,使用synchronize等待的线程会一直等待下去,不能够响应中断;通过Lock可以知道是否成功获取了锁,而synchronize却做不到。

    6.*解释一下什么是线程池?Java自带有哪几种线程池?

    在面向对象编程中,创建和销毁对象是很浪费时间的,因为创建一个对象需要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是“池化资源”技术产生的原因。线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中。需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
    Java通过Executors提供四种线程池,分别为:

    1.newCachedThreadPool

    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。这种类型的线程池特点是:
    工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger.MAX_VALUE),这样可灵活的往线程池中添加线程。
    如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
    在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

    2.newFixedThreadPool

    创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。FixedThreadPool是一个典型且优秀的线程池,它具有提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。

    3.newSingleThreadPool

    创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。如果这个线程异常接收,会有另一个取代他,保证顺序执行。单工作线程最大的特点是可以保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

    4.newScheduleThreadPool

    创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。延迟3秒执行。

    展开全文
  • 问题4-27:在因特网中最常见的分组长度大约是多少个字节? 问题4-28:IP数据报的最大长度是多少个字节? 问题4-29:IP数据报的首部的最大长度是多少个字节?典型的IP数据报首部是多长? 问题4-30:IP数据报在传输的...
  • 107.spring boot 配置文件有哪类型?它们有什么区别? 108.spring boot 有哪些方式可以实现热部署? 109.jpa 和 hibernate 有什么区别? 110.什么是 spring cloud? 111.spring cloud 断路器作用是什么? 112....
  • 引用类型和原始类型具有不同特征和用法,它们包括:大小和速度问题,这种类型以哪种类型数据结构存储,当引用类型和原始类型用作某个类实例数据时所指定缺省值。对象引用实例变量缺省值为 null,而原始...
  • 21、注册Jdbc驱动程序的三种方式 109 22、用JDBC如何调用存储过程 109 23、JDBC中PreparedStatement相比Statement好处 110 24. 写一个用jdbc连接并访问oracle数据程序代码 111 25、Class.forName作用?为什么...
  • 问题1-16:在教材1.5.2节提到协议有三个要素,即语法、语义和同步。语义是否已经包括了同步的意思? 问题1-17:为什么协议不能设计成100%可靠? 问题1-18:什么是因特网穆尔定律? 问题1-19:局域网、广域网和...
  • 操作系统概念

    2020-05-06 01:11:10
    操作系统概念 什么是操作系统 系统调用 进程和线程 进程和线程区别 从个角度来剖析二者之间区别 ...select/poll/epoll区别 ...进程有哪状态 进程间同步方式 临界区概念 同步与互斥...

    操作系统概念

    什么是操作系统

    • 操作系统(Operating System,简称OS)是管理计算机硬件与软件资源的程序,是计算机系统的内核与基石;
    • 操作系统本质上是运行在计算机上的软件程序 ;
    • 操作系统为用户提供一个与系统交互的操作界面 ;

    操作系统的功能组成

    • 用户和接口管理: 负责用户身份核准、操作权限管理以及各种人机接口的实现。
    • 处理机管理: 围绕CPU的调度,负责管理、控制用户程序的动态执行过程
      • 进程控制和管理;进程同步和互斥;进程通信;进程死锁;线程控制和管理;四级调度。
    • 存储管理: 负责为正在运行的程序分配内存空间,并实现地址和空间有关的管理功能
      • 内存分配;地址转换;存储保护;内存共享;存储扩充
    • 设备管理: 负责外存和I/O设备的分配、驱动和调度控制,以及实现外设读写的相关机制。
      • 设备的分配和回收;设备的驱动调度;实现逻辑设备到物理设备之间的映射;
      • 提供设备中断处理;提供缓冲区管理;实现虚拟设备;
    • 文件管理: 负责文件的建立、存取、目录管理、共享保护以及文件存储空间的管理。
      • 提供文件的逻辑组织方法;提供文件的物理组织方法;提供文件的存取和使用方法;
      • 实现文件的目录管理;实现文件的共享和安全性控制;实现文件的存储空间管理
    • 网络与通信管理等

    操作系统主要特征

    • 并发性(Concurrency):在一个时间段内,多个程序处于宏观的运行状态,并发推进。
    • 共享性(Sharing): 共享性指操作系统中的资源可被多个并发执行的进程所使用 。
    • 异步性(Async):异步性也被称为不确定性,指的是并发进程的推进速度不可预知。每个进程在某一时刻所处的状态以及资源拥有情况,不是提前安排好的,而是系统动态运行过程中通过管理调度形成的。
      • 异步性特征是并发和共享带来的结果。
    • 虚拟性(Virtuality):虚拟性是指利用某种技术将少的物理资源演变为多的、逻辑上的对应资源;

    系统调用

    根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:

    • 用户态(user mode) : 用户态运行的进程或可以直接读取用户程序的数据。只能受限地访问内存,且不允许访问外围设备,没有占用CPU的能力,CPU资源可以被其它程序获取;
    • 系统态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。

    我们运行的程序基本都是运行在用户态,如果我们调用操作系统提供的系统态级别的子功能咋办呢?那就需要系统调用了!

    系统调用:是应用程序与OS的接口, 也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。

    系统调用按功能大致可分为如下几类:

    • 设备管理。完成设备的请求或释放,以及设备启动等功能。
    • 文件管理。完成文件的读、写、创建及删除等功能。
    • 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
    • 进程通信。完成进程之间的消息传递或信号传递等功能。
    • 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。

    进程和线程

    进程和线程的区别

    • 进程是什么

      • 进程是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,也就是说进程是可以独立运行的一段程序
        • a. 从原理角度看,进程是支持程序执行的一种系统机制,它对处理器上运行程序的活动进行抽象
        • b. 从实现角度看,进程是一种数据结构,用来准确地刻画运行程序的状态和系统动态变化状况
    • 线程是什么

      • 线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。在运行时,只是暂用一些计数器、寄存器和栈 。
    • 操作系统中引入进程的目的是为了使多个程序并发执行,以改善资源使用率和提高系统效率

    • 操作系统中再引入线程,则是为了减少程序并发执行时所付出的时空开销,使得并发粒度更细、并发性更好。

    从三个角度来剖析二者之间的区别

    • 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
    • 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行
    • 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源

    什么是协程

    协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

    协程与线程进行比较

    • 一个线程可以拥有多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。
    • 线程进程都是同步机制,而协程则是异步
    • 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态

    进程调度功能

    • 根据进程当前状态决定哪个进程获得CPU,以及占用多长时间。
    • 将CPU分给进程。

    调度方式

    • 非抢占式调度: 当前进程主动放弃处理机控制权
    • 抢占式调度:主要指在系统正常运转期间,如果某种事件出现,系统将迫使正在运行的进程停下来,将CPU控制权交给其它进程。

    调度算法

    进程的调度算法是为了确定首先执行哪个进程以及最后执行哪个进程以实现最大CPU利用率,有以下几类

    • 先到先服务(FCFS)调度算法 : 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用CPU时再重新调度。
    • 短作业优先(SJF)的调度算法 : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用CPU时再重新调度。
      时间片轮转调度算法 : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法,又称RR(Round robin)调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
    • 多级反馈队列调度算法 :前面介绍的几种进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,因而它是目前被公认的一种较好的进程调度算法,UNIX操作系统采取的便是这种调度算法。
    • 优先级调度 :为每个流程分配优先级,首先执行具有最高优先级的进程,依此类推。具有相同优先级的进程以FCFS方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。

    进程有哪几种状态

    • 运行状态 :进程得到CPU控制权,它的程序正在运行。(在系统中,总只有一个进程处于此状态)
    • 就绪状态:已经准备就绪,一旦得到CPU,就立即可以运行。(有多个进程处于此状态)
    • 阻塞状态:正在等待某个事件的发生(如等待I/O的完成),而暂停执行,这时,即使给它CPU时间,它也无法执行。

    在这里插入图片描述

    进程间同步方式

    进程的同步是目的,而进程间通信是实现进程同步的手段

    临界区概念

    • 并发进程中与共享变量有关的程序段称为临界区(Critical Section)。
    • 共享变量所代表的资源称为临界资源(Critical Resource),即一次仅能供一个进程使用的资源。

    同步与互斥的概念

    • 同步:多个进程因为合作而使得进程的执行有一定的先后顺序。比如某个进程需要另一个进程提供的消息,获得消息之前进入阻塞态;体现协作关系。
    • 互斥:多个进程在同一时刻只有一个进程能进入临界区,体现竞争关系

    进程间的通信方式

    • 管道/匿名管道(Pipes) :用于具有亲缘关系的父子进程间或者兄弟进程之间的通信。
    • 有名管道(Names Pipes) : 匿名管道由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道严格遵循先进先出(first in first out)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
    • 信号(Signal) :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生,比如 Linux 中的 SIGKILL信号
    • 消息队列(Message Queuing) :消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更有优势。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺。
    • 信号量(Semaphores) :信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
    • 共享内存(Shared memory) :使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
    • 套接字(Sockets) : 此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。

    在这里插入图片描述

    线程间的同步方式

    线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。操作系统一般有下面三种线程同步的方式:

    • 互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
    • 信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
    • 事件(Event) :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操做
    • 临界区 Critical Section:任意时刻只允许一个线程对临界资源进行访问。拥有临界区对象的线程可以访问该临界资源,其它试图访问该资源的线程将被挂起,直到临界区对象被释放。

    什么是死锁

    在两个或者多个并发进程中,每个进程持有某种资源而又等待其它进程释放它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁(deadlock)。

    死锁产生的必要条件

    • 互斥:一个资源一次只能被一个进程使用;
    • 占有并等待:一个进程至少占有一个资源,并在等待另一个被其它进程占用的资源;
    • 非抢占:已经分配给一个进程的资源不能被强制性抢占,只能由进程完成任务之后自愿释放;
    • 循环等待:若干进程之间形成一种头尾相接的环形等待资源关系,该环路中的每个进程都在等待下一个进程所占有的资源。

    死锁起因

    • 资源不足
    • 进程推进顺序非法

    操作系统内存管理基础

    内存管理介绍

    • 内存分配:操作系统的内存管理主要负责内存的分配与回收(malloc 函数:申请内存,free 函数:释放内存)
    • 地址映射: 地址映射也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情。
    • 内存保护: 检查地址的合法性,防止越界访问
    • 内存扩充: 解决“求大于供”的问题,采用虚拟存储技术

    常见的几种内存管理机制

    • 简单分为连续分配管理方式和非连续分配管理方式这两种。

      • 连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如 块式管理 。
      • 非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如页式管理 和 段式管理。
    • 块式管理 :将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片。

    • 页式管理 :把主存分为大小相等且固定的一页一页的形式,页较小,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。这里有两点需要注意: 1
      虚拟地址到物理地址的转换要快。2.虚拟地址空间大,页表也会很大的问题。

    • 段式管理 :页式管理虽然提高了内存利用率,但是页式管理其中的页实际并无任何实际意义。段式管理把主存分为一段段的,每一段的空间又要比一页的空间小很多 。但是,最重要的是段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。段式管理通过段表对应逻辑地址和物理地址。

    • 段页式管理机制: 段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页

    快表和多级页表
    • 快表

    为了解决虚拟地址到物理地址的转换速度,操作系统在 页表方案 基础之上引入了 快表 来加速虚拟地址到物理地址的转换(用来存放进程最近访问的部分页表项)。我们可以把块表理解为一种特殊的高速缓冲存储器(Cache),其中的内容是页表的一部分或者全部内容。作为页表的Cache,它的作用与页表相似,但是提高了访问速率。由于采用页表做地址转换,读写内存数据时CPU要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。

    使用快表之后的地址转换流程是这样的:

    • 根据虚拟地址中的页号查快表;

    • 如果该页在快表中,直接从快表中读取相应的物理地址;

    • 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;

    • 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。

    • 多级页表

    引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中。

    分页机制和分段机制的共同点和区别

    • 共同点 :

    分页机制和分段机制都是为了提高内存利用率,较少内存碎片。
    页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。

    • 区别 :

    页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。
    分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。

    虚拟内存

    每个程序都拥有自己的地址空间,这个地址空间被分成大小相等的页,这些页被映射到物理内存;但不需要所有的页都在物理内存中,当程序引用到不在物理内存中的页时,由操作系统将缺失的部分装入物理内存。这样,对于程序来说,逻辑上似乎有很大的内存空间,只是实际上有一部分是存储在磁盘上,因此叫做虚拟内存。

    基本特征

    • 虚拟扩充:不是物理上,而是逻辑上扩充了内存容量
    • 部分装入: 每个作业(进程)不是全部一次性地装入内存,而是只装入其一 部分
    • 离散分配: 每个作业(进程)装入内存的那部分不必占用连续的内存空间,而是“见缝插针”
    • 多次对换: 在一个进程运行期间,它所需的全部程序和数据要分成多次调入内存

    如何进行地址空间到物理内存的映射

    内存管理单元(MMU)管理着逻辑地址和物理地址的转换,其中的页表(Page table)存储着页(逻辑地址)和页框(物理内存空间)的映射表,页表中还包含包含有效位(是在内存还是磁盘)、访问位(是否被访问过)、修改位(内存中是否被修改过)、保护位(只读还是可读写)。逻辑地址:页号+页内地址(偏移);每个进程一个页表,放在内存,页表起始地址在PCB/寄存器中。

    有哪些页面置换算法

    在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘中来腾出空间。页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。

    • 最佳页面置换算法OPT(Optimal replacement algorithm):置换以后不需要或者最远的将来才需要的页面,是一种理论上的算法,是最优策略;
    • 先进先出FIFO:置换在内存中驻留时间最长的页面。缺点:有可能将那些经常被访问的页面也被换出,从而使缺页率升高;
    • 第二次机会算法SCR:按FIFO选择某一页面,若其访问位为1,给第二次机会,并将访问位置0;
    • 时钟算法 Clock:SCR中需要将页面在链表中移动(第二次机会的时候要将这个页面从链表头移到链表尾),时钟算法使用环形链表,再使用一个指针指向最老的页面,避免了移动页面的开销;
    • 最近未使用算法NRU(Not Recently Used):检查访问位R、修改位M,优先置换R=M=0,其次是(R=0, M=1);
    • 最近最少使用算法LRU(Least Recently Used):置换出未使用时间最长的一页;实现方式:维护时间戳,或者维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。
    • 最不经常使用算法NFU:置换出访问次数最少的页面

    什么是IO多路复用?怎么实现

    IO多路复用(IO Multiplexing)是指单个进程/线程就可以同时处理多个IO请求。

    实现原理:用户将想要监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符就绪(读就绪或写就绪),或者超时(设置timeout),函数就会返回,然后该进程可以进行相应的读/写操作。

    select/poll/epoll三者的区别

    • select:
      • 将文件描述符放入一个集合中,调用select时,将这个集合从用户空间拷贝到内核空间(缺点1:每次都要复制,开销大),由内核根据就绪状态修改该集合的内容。(缺点2)集合大小有限制,32位机默认是1024(64位:2048);
      • 采用水平触发机制。select函数返回后,需要通过遍历这个集合,找到就绪的文件描述符(缺点3:轮询的方式效率较低),当文件描述符的数量增加时,效率会线性下降
    • poll:和select几乎没有区别,区别在于文件描述符的存储方式不同,poll采用链表的方式存储,没有最大存储数量的限制;
    • epoll:
      • 通过内核和用户空间共享内存,避免了不断复制的问题;支持的同时连接数上限很高(1G左右的内存支持10W左右的连接数);
      • 文件描述符就绪时,采用回调机制,避免了轮询(回调函数将就绪的描述符添加到一个链表中,执行epoll_wait时,返回这个链表);
      • 支持水平触发和边缘触发,采用边缘触发机制时,只有活跃的描述符才会触发回调函数。

    总结,区别主要在于:

    • 一个线程/进程所能打开的最大连接数
    • 文件描述符传递方式(是否复制)
    • 水平触发 or 边缘触发
    • 查询就绪的描述符时的效率(是否轮询)

    什么时候使用select/poll,什么时候使用epoll

    当连接数较多并且有很多的不活跃连接时,epoll的效率比其它两者高很多;但是当连接数较少并且都十分活跃的情况下,由于epoll需要很多回调,因此性能可能低于其它两者。

    什么是水平触发?什么是边缘触发

    • 水平触发(LT,Level Trigger)模式下,只要一个文件描述符就绪,就会触发通知,如果用户程序没有一次性把数据读写完,下次还会通知;
    • 边缘触发(ET,Edge Trigger)模式下,当描述符从未就绪变为就绪时通知一次,之后不会再通知,直到再次从未就绪变为就绪(缓冲区从不可读/写变为可读/写)。
    • 区别:边缘触发效率更高,减少了被重复触发的次数,函数不会返回大量用户程序可能不需要的文件描述符。
      为什么边缘触发一定要用非阻塞(non-block)IO:避免由于一个描述符的阻塞读/阻塞写操作让处理其它描述符的任务出现饥饿状态。

    有哪些常见的IO模型

    • 同步阻塞IO(Blocking IO):用户线程发起IO读/写操作之后,线程阻塞,直到可以开始处理数据;对CPU资源的利用率不够;
    • 同步非阻塞IO(Non-blocking IO):发起IO请求之后可以立即返回,如果没有就绪的数据,需要不断地发起IO请求直到数据就绪;不断重复请求消耗了大量的CPU资源;
    • IO多路复用: 让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作。
    • 异步IO(Asynchronous IO):用户线程发出IO请求之后,继续执行,由内核进行数据的读取并放在用户指定的缓冲区内,在IO完成之后通知用户线程直接使用。
    展开全文
  • - global.module 最常见的模块输出 - global.require() 模块引入 - global.console()、setInterval()、setTimeout() 这些浏览器端的方法也在global对象下面 在命令行里执行一次 global 一切就都懂了。 <h2>process ...
  • c++面试题基础分享.doc

    2020-03-24 21:40:59
    27.列举几进程的同步机制,并比较其优缺点 28.数组和链表的区别 29.MFC主要要用到几个类?及其各个类的作用 30.MFC六大核心机制 31.OnDraw和OnPaint 32.win32程序的消息响应机制是如何实现的 33.MFC中的...
  • java面试宝典

    2013-02-28 16:04:01
    同步有实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象一个synchronized方法后,其它线程是否可进入此对象其它方法? 18 73、线程基本概念、线程基本状态...
  • 39、说出十种常见的异常 22 40什么是检查性异常和非检查性异常? 23 41、Java的异常处理机制是什么? 23 42、一个静态方法,里面可不可以用this和super关键字 24 、JavaScript/JQuery/Ajax部分 24 1、用js和jQuery...
  • 1.1.8 NFS 和 SMB 是最常见的 NAS(Network Attached Storage)协议,当把一个文件系统同时通过 NFS 和 SMB 协议共享给多个主机访问时,以下哪些说法是错误的 1.1.9 输入 ping IP 后敲回车,发包前会发生什么?...
  • 千方百计笔试题大全

    2011-11-30 21:58:33
    同步有实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象一个synchronized方法后,其它线程是否可进入此对象其它方法? 18 73、线程基本概念、线程基本状态...
  • java面试题

    2018-01-01 15:35:15
    hibernate的三种状态之间如何转换 59 71.6. Hibernate并发机制,并发问题处理。 59 71.6.1. Hibernate并发机制 59 71.6.2. 并发问题解决方案 59 71.7. Hibernate是如何延迟加载? 60 71.8. Hibernate中怎样实现类...
  • 最新Java面试宝典pdf版

    热门讨论 2011-08-31 11:29:22
    21、注册Jdbc驱动程序的三种方式 109 22、用JDBC如何调用存储过程 109 23、JDBC中PreparedStatement相比Statement好处 110 24. 写一个用jdbc连接并访问oracle数据程序代码 111 25、Class.forName作用?为什么...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    除了使用new关键字创建对象意外,试列举另外三种以上创建实例方式? 37.classloader中,JDKAPI、Classpath中同web-inf中class加载方式什么区别? 38.列举三种以上垃圾回收算法,并比较其优缺点? 39....
  • java面试题典 java 面试题 经典

    热门讨论 2010-06-18 13:42:36
    解析XML文档有哪方式? 13 39. JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗? 14 40. 一个".java"源文件中是否可以包括多个类(不是内部类)...
  • Java面试宝典2010版

    2011-06-27 09:48:27
    21、注册Jdbc驱动程序的三种方式 22、用JDBC如何调用存储过程 23、JDBC中PreparedStatement相比Statement好处 24. 写一个用jdbc连接并访问oracle数据程序代码 25、Class.forName作用?为什么要用? 26、大...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    部分 面向对象 C#.101 第九章 面向对象程序设计 .101 9.1 面向对象基本概念.101 9.2 对象模型技术 .103 9.3 面向对象分析 .105 9.4 面向对象设计 .107 9.5 小 结 .110 第十章 类 .112 ...
  • 获取 Spring 容器中 Bean 时提供了三种获取方式: 通过name获取 Bean. 通过class获取Bean. 通过name,以及Clazz返回指定Bean 详情移步:...
  • 书中内容主要集中在大多数企业常见的问题之上,如安装和升级到oracle database 11g数据库软件、创建数据库、导出和导入数据、数据库的备份与恢复、性能调优,等等。  本书还提供了dba完成本职工作必备的基本的uniix...
  • java 面试题 总结

    2009-09-16 08:45:34
    引用类型和原始类型具有不同特征和用法,它们包括:大小和速度问题,这种类型以哪种类型数据结构存储,当引用类型和原始类型用作某个类实例数据时所指定缺省值。对象引用实例变量缺省值为 null,而原始...
  • 52、 常见的Caching技术://ASP.NET Cache //数据库缓存 //通过静态变量缓存//Memory-Mapped Files 53、 授权包括://用户的权限//代码的执行权限 54、 在构思阶段,各种角色的职责是://根据质量目标提供反馈//...
  • C#微软培训资料

    2014-01-22 14:10:17
    部分 面向对象 C#.101 第九章 面向对象程序设计 .101 9.1 面向对象基本概念.101 9.2 对象模型技术 .103 9.3 面向对象分析 .105 9.4 面向对象设计 .107 9.5 小 结 .110 第十章 类 .112 ...
  • 需求模型表现形式自然语言、半形式化(如图、表、结构化英语等)和形式化表示等三种。需求概念模型要求包括实现独立性:不模拟数据表示和内部组织等;需求模拟技术又分为企业模拟、功能需求模拟和非功能需求...
  • java基础题 很全面

    2009-05-09 09:24:24
    同步有实现方法,都是什么? 12 45. 线程基本概念、线程基本状态以及状态之间关系 12 46. 在linux下 怎么查看tomcat进程? 12 47. 简述逻辑操作(&,|,^)与条件操作(&&,||)区别。 12 48. XML文档定义有几...
  • ● 增强安全性:每个程序集还可以包含内置安全信息,这些信息可以准确地指出哪种类型用户或进程可以调用什么类哪些方法。这样就可以非常准确地控制用户部署程序集使用方式。 ● 对安装没有任何影响:...
  • asp.net知识库

    2015-06-18 08:45:45
    常见的 ASP.NET 2.0 转换问题和解决方案 Asp.Net2.0无刷新客户端回调 体验.net 2.0 的优雅(1) -- 异步WebService调用 ASP.NET 2.0页面框架的几点新功能 ASP.NET 2.0 中收集的小功能点 asp.net2.0中的webpart使用...

空空如也

空空如也

1 2 3
收藏数 46
精华内容 18
关键字:

常见的同步有哪三种