博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java并发相关(5)---并发理论相关
阅读量:4075 次
发布时间:2019-05-25

本文共 3156 字,大约阅读时间需要 10 分钟。

  目录: 
     1、多线程介绍
    2、线程运行流程
    3、线程安全
    4、synchronized、volatile、锁
    5、CAS 介绍
    
    一、多线程相关介绍
    1、什么是多线程,多线程的优劣?
          多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。
        可以提高 CPU 的利用率。在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,
        这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
        
    2、什么是线程,什么是进程?
        1) 进程,一个在内存运行中应用程序,每个进程有自己独立内存空间,一个进程可以有多个线程。比如,qq.exe。
        2) 线程,进程中的一个执行任务,负责当前进程中程序执行,一个进程至少一个线程或多个,多个线程可以共享内存空间。

    3、多线程时如何指定线程数量

        1)cup密集型,即程序主要以计算运行等为主,设定线程数量等于cpu核数+1。
        2) io密集型,即程序以一些io操作为主,这个就要考虑io空闲比例是多少,比如是90%,那么就设置为cup核数/(1-90%)。
        3) 兼顾,综合上面二个计算方式。

  二、线程运行状态

    1、线程的运行状态
      1)创建: new Thread(),创建一个线程。
      2) 可运行(runnable):线程对象创建后,当调用线程对象的 start()方法,等待cup调度,获取cpu的使用权。
      3) 运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。
      4) 消亡(dead):线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
      5) 阻塞状态: 分为同步阻塞(锁池等待锁),等待阻塞(等待池等待-释放锁),其他阻塞(不释放锁)。
            同步阻塞:线程在获取锁时失败,锁被其他线程占用,线程就进入锁池,线程会进入同步阻塞状态。
            等待阻塞:运行状态中的线程执行 wait()方法,该线程放入等待队列中,此时就进入到等待阻塞状态。
            其他阻塞:leep(),join, io停顿 线程会进入到阻塞状态,当上列三个操作完成,线程又转入就绪状态。

   

    2、sleep() 和 wait() 有什么区别?
      两者都可以暂停线程的执行,sleep() 不释放锁;wait() 释放锁,sleep是Thread静态方法,wait是Object方法。
      Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
    
    3、notify() 和 notifyAll() 有什么区别?
        notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则
     留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。
     

三、线程安全

        
1、什么是线程安全: 当【多个线程】访问一个类时,这个类【不需要额外协调】,这个类始终都能够表现正确的行为,那么这
个类就是线程安全的。显然只有资源竞争时才会导致线程不安全,因此【无状态对象永远是线程安全】的。
  
2、并发编程三要素是什么?在 Java 程序中怎么保证多线程的运行安全?
      原子性:原子,即一个不可再被分割的颗粒。原子性指的是一个或多个操作要么全部执行成功要么全部执行失败。(synchronized)
    可见性:一个线程对共享变量的修改,另一个线程能够立刻看到。(synchronized,volatile)
    有序性:程序执行的顺序按照代码的先后顺序执行。(处理器可能会对指令进行重排序)(synchronized,volatile)

    synchronized保证了原子性,那么如何保证可见性?在开始执行时会加锁,执行完成后会进行解锁,但在一个变量解锁之前,必须先把此变量

    同步回主存中,这样解锁后,后续其它线程就可以访问到被修改后的值,从而保证可见性。
    volatile:关键字就是保证可见性,以及指令重排序,即有序性。        
    
 四、synchronized、volatile、锁
      (1)synchronized 是悲观锁,属于抢占式,会引起其他线程阻塞。
      (2)volatile 提供多线程共享变量可见性和禁止指令重排序优化。
      (3)CAS 是基于冲突检测的乐观锁(非阻塞)
        
  1、volatile关键字
      概念:volatile来保证可见性和禁止指令重排。 volatile 提供happens-before 的保证,确保一个线程的修改能对其他线程
  是可见的。当一个共享变量被 volatile 修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时, 它会去内存中读取新值。
       使用规则:
           1)运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
        2)变量不需要与其他状态变量共同参与不变约束
           范例:一般用作状态标记使用。(单例懒汉的null判断等)
    
  2、synchronized关键字
      jdk中用来加锁的关键字,锁住一个方法或者代码块,锁对象如果是实例方法就是实例对象,是静态方法就是class,代码块为代码块中指定的
      对象。jdk1.6之后,该关键字被进行了很多的优化,锁可以从偏向锁、轻量级锁(自旋锁、自旋自适应锁)、重量级锁
        
    1) 偏向锁,即锁会偏向于第一个获得它的线程,如果一直没有其他线程来竞争,那么持有偏向锁的线程将永远不需要进行同步操作。
    
    2) 轻量级锁,偏向锁有其他线程来竞争锁就升级成轻量级锁-自旋。所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,
    而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁的。
    
    3) 重量级锁,轻量级锁膨胀之后,就升级为重量级锁了。
        
    
  3、锁按功能特点可以分为--可重入锁、公平锁/非公平锁、独占锁/共享锁
      
      1) 可重入锁,synchronized的锁是可重入的,即已经获得锁去执行锁保护的另外一个方法还是可以执行的,原理利用
   锁对象维护着一个记录着被锁次数的计数器,当同一个线程再次获得该对象的锁的时候,计数器自增。这个再次操作释放
   时,计数器自减。当计数器为0的时候。锁将被释放,其他线程便可以获得锁。
   
      2) 公平锁/非公平锁
       公平锁: 是指多个线程按照申请锁的顺序来获取锁,类似于排队,FIFO规则
        非公平锁: 是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获到锁,在高并发的情况下,有可能造成优先级反转或者饥饿现象。
     
    3) 独占锁/共享锁
      独占锁: 指该锁一次只能被一个线程所持有。对ReentrantLock和Synchronize而言都是独占锁。
      共享锁: 指该锁可被多个线程所持有。
    
        
 五、cas 
     
    CAS 是 compare and swap 的缩写,即我们所说的比较交换。
        cas 是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将
        资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一
        种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加 version 来获取数据,
        性能较悲观锁有很大的提高。
        CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面
        的值和 A 的值是一样的,那么就将内存里面的值更新成 B。CAS是通过无限循环来获取数据的
        ,若果在第一轮循环中,a 线程获取地址里面的值被b 线程修改了,那么 a 线程需要自旋,到
        下次循环才有可能机会执行。
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
 

转载地址:http://ueuni.baihongyu.com/

你可能感兴趣的文章
本科生的编程水平到底有多高
查看>>
Solr及Spring-Data-Solr入门学习
查看>>
python_time模块
查看>>
python_configparser(解析ini)
查看>>
selenium学习资料
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
Golang 数据可视化利器 go-echarts ,实际使用
查看>>
mysql 跨机器查询,使用dblink
查看>>
mysql5.6.34 升级到mysql5.7.32
查看>>
dba 常用查询
查看>>
Oracle 异机恢复
查看>>
Oracle 12C DG 搭建(RAC-RAC/RAC-单机)
查看>>
Truncate 表之恢复
查看>>