• 线程、volatile与synchronized、Lock


    线程

    1、概念:

    进程是程序运行资源分配的最小单位

    线程CPU调度的最小单位,必须依赖于进程而存在。

    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的、能独立运行的基本单位。

    2、线程生命周期:

    线程生命周期的5种状态:

    Java线程具有五中基本状态

    新建状态(New):当线程对象被创建后,即进入了新建状态,如:Thread t = new MyThread();

    就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

    运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

      注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

      (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待队列中。
      (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
      (三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    结束状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    Tip:

    当调用线程的yield()方法时,线程从运行状态转换为就绪状态,但接下来CPU调度就绪状态中的哪个线程具有一定的随机性,因此,可能会出现A线程调用了yield()方法后,接下来CPU仍然调度了A线程的情况。

    3、线程调度

    共同点:

    1. wait()和sleep()他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
    2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态
      不同点
    3. Thread类的方法:sleep(),yield()等
      Object对象的方法:wait()和notify()等
    4. 每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。
      sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法
    5. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
    6. sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

    4、线程实现

    4.1、实现方式

      继承Thread覆盖run()方法

      实现Runnable接口,实现run()方法

      实现Callable接口,实现call()方法

    4.2、之间的区别:

    4.2.1、Thread类与Runnable接口区别:

        Thread:每个线程都独立,不共享资源

        Runnable:存在线程共享概念

    4.2.2、Runnable和Callable的区别:

    两者最大的不同点是:
    
    1)是否能返回执行结果:
    
    	<font color=red>实现Callable接口的任务线程**能返回执行结果**;而实现Runnable接口的任务线程**不能返回结果**</font>;
    
    2)方法是否能抛出异常:
    
    	Callable接口的<font color=red>call()方法**允许抛出异常**</font>;而Runnable接口的<font color=red>run()方法的异常只能在内部消化,**不能继续上抛**</font>;
    

    5、线程安全

    线程安全性包括两方面:可见性和原子性。

    5.1、volatile与synchronized

    5.1.1、volatile

    volatile关键字解决的是内存可见性的问题:

    可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
    使用volatile修饰的变量会强制将修改的值立即写入主存,主存中值的更新会使缓存中的值失效。这时候会去主内存读取。

    5.1.2、volatile与synchronized区别

    1) volatile轻量级,只能修饰变量synchronized重量级,可以修饰变量、方法、类

    2) volatile只能保证数据的内存可见性,不能保证原子性,因为多个线程并发访问volatile修饰的变量不会阻塞。

    synchronized不仅保证内存可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。

    一个线程执行临界区代码过程如下:
        1 获得同步锁
        2 清空工作内存
        3 从主存拷贝变量副本到工作内存
        4 对这些变量计算
        5 将变量从工作内存写回到主存
        6 释放锁

    所以说:仅仅使用volatile并不能保证线程安全性。而synchronized则可实现线程的安全性。

    5.1、synchronized关键字的使用和缺点

    1)、获取锁的线程执行完毕,然后线程释放对锁的占有
    2)、线程执行发生异常,此时JVM会让线程自动释放锁
    缺点:

    即使大量读操作也会堵塞,不会并发去读。如果线程中有堵塞超时任务,其他任务也不会往下执行,全部堵塞了。

    5.2、Lock

    5.2.1、Lock接口中常用方法

      lock()
      tryLock() :尝试获取锁
      tryLock(long time, TimeUnit unit):按照超时时间获取锁
      lockInterruptibly():打断锁(注意,当一个线程获取了锁之后,是不会被interrupt()方法中断的)
      unLock():释放锁

    5.2.2、lock线程间的通信:

    Conditon中的await()对应Object的wait();
    Condition中的signal()对应Object的notify();
    Condition中的signalAll()对应Object的notifyAll()

    5.2.3、ReentrantLock(可重入锁)

    ReentrantLock支持两种获取锁的方式,一种是公平模型,一种是非公平模型。

    公平锁:保证执行顺序,先进先出,FIFO

    非公平锁:JVM优化后一种插队模式,后进先出,LIFO(先进的数据可能一直消费不到)

    5.2.4、ReentrantReadWriteLock (读写锁)

    允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。

    相对于排他锁,提高了并发性。

    在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。

    5.3、lock和synchronized区别:

    Lock和synchronized的选择:

    类别 synchronized Lock
    存在层次 Java的关键字,在jvm层面上 是一个接口
    锁的释放 1、以获取锁的线程执行完同步代码,释放锁
    2、线程执行发生异常,jvm会让线程释放锁
    在finally中必须释放锁,不然容易造成线程死锁
    锁的获取 假设A线程获得锁,B线程等待。
    如果A线程阻塞,B线程会一直等待
    分情况而定,Lock有多个锁获取的方式,可以尝试获得锁,线程可以不用一直等待
    锁状态 无法判断 可以判断
    锁类型 可重入
    不可中断
    非公平
    可重入
    可判断
    可公平(两者皆可)
    性能 少量同步 大量同步

    Lock可以提高多个线程进行读操作的效率。

    6、守护线程

    守护线程,可以理解为后台运行线程。进程结束,守护线程自然而然地就会结束,不需要手动的去关心和通知其状态。Java的垃圾回收也是一个守护线程。

    它的好处就是你不需要关心它的结束问题。

  • 相关阅读:
    四月十五号日报
    四月十一号日报
    四月八号日报
    五月六号日报
    CCSUOJ评测系统——第四次scrum冲刺
    CCSUOJ评测系统——第三次scrum冲刺
    CCSUOJ评测系统——第二次scrum冲刺
    C# Process 进程管理
    [C#][收集整理]
    [C#][收集整理]
  • 原文地址:https://www.cnblogs.com/amunamuna/p/10287875.html
Copyright © 2020-2023  润新知