多线程和锁连杀

  1. 什么是线程,什么是进程
    进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,拥有独立的内存单元,是一个动态概念,竞争计算机系统资源的基本单位。
    线程:是进程的一个执行单元,是进程内的调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位

  2. 线程状态转换
    从jdk代码中,可以看出,对线程定义的状态有如下几种:
    JDK代码:

      /**
     * A thread state.  A thread can be in one of the following states:
     * <ul>
     * <li>{@link #NEW}<br>
     *     A thread that has not yet started is in this state.
     *     </li>
     * <li>{@link #RUNNABLE}<br>
     *     A thread executing in the Java virtual machine is in this state.
     *     </li>
     * <li>{@link #BLOCKED}<br>
     *     A thread that is blocked waiting for a monitor lock
     *     is in this state.
     *     </li>
     * <li>{@link #WAITING}<br>
     *     A thread that is waiting indefinitely for another thread to
     *     perform a particular action is in this state.
     *     </li>
     * <li>{@link #TIMED_WAITING}<br>
     *     A thread that is waiting for another thread to perform an action
     *     for up to a specified waiting time is in this state.
     *     </li>
     * <li>{@link #TERMINATED}<br>
     *     A thread that has exited is in this state.
     *     </li>
     * </ul>
     *
     * <p>
     * A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
     *
     * @since   1.5
     * @see #getState
     */
    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,
    
        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,
    
        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,
    
        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,
    
        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,
    
        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }
    

    线程状态:

    状态 描述
    NEW(新建) 线程新建但是还没有start的时候,即new Thread()
    RUNNABLE(就绪) 调用了Threadstart()方法,此时线程可运行,但是也有可能需要等待其他操作系统资源,比如处理器资源,当获取到处理器资源之后,则进入RUNNING状态
    BLOCKED(阻塞) 当进入同步代码块时,如果需要等待获取锁,那么就会被阻塞进入该状态
    WAITING(等待) 由于执行了Object.wait()Thread.join()LockSupport.park()进入了等待状态
    TIMED_WAITING(有限时长等待) 由于执行了Thread.sleepObject.wait(long)、Thread.join(long)、LockSupport.parkNanosLockSupport.parkUntil,进入了有限时长的等待状态
    TERMINATED(结束) 线程run方法执行结束

    各状态转换如下:
    在这里插入图片描述

  3. 为何使用线程池,线程池的原理
    好处: 线程是一个资源,切换上下文也需要消耗资源,利用线程池可以减少线程的创建和线程的上下文切换,节约资源。
    原理: 详见ThreadPoolExecutor

  4. 手写生产者消费者模型

    1. 基于BlockingQueue实现
      class Producer implements Runnable {
          private final BlockingQueue queue;
          Producer(BlockingQueue q) { queue = q; }
          public void run() {
              try {
                 while (true) { queue.put(produce()); }
              } catch (InterruptedException ex) { ... handle ...}
          }
         Object produce() { ... }
      }
      
      class Consumer implements Runnable {
         private final BlockingQueue queue;
         Consumer(BlockingQueue q) { queue = q; }
         public void run() {
             try {
                 while (true) { consume(queue.take()); }
             } catch (InterruptedException ex) { ... handle ...}
          }
          void consume(Object x) { ... }
      }
      
      class Setup {
         void main() {
             BlockingQueue q = new SomeQueueImplementation();
             Producer p = new Producer(q);
             Consumer c1 = new Consumer(q);
             Consumer c2 = new Consumer(q);
             new Thread(p).start();
             new Thread(c1).start();
             new Thread(c2).start();
         }
      }
      
    2. 基于notify/wait()实现
       // todo: 添加对应代码
      
    3. 基于lock实现
       // todo: 添加对应代码
      
  5. 实现同步的方式及其区别
    synchronized & ReentrantLock

    1. 都是可重入锁;
      可重入锁: 可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁

    2. ReentrantLock支持更多特性:
      可等待,可中断,可多条件,可公平锁

      公平锁: 加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。
      非公平所: 线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。

      ReentrantLock非公平锁的实现:

      static final class NonfairSync extends Sync {
          final void lock() {
              // 非公平锁实现,获取锁时不是直接添加到队列末尾,而是先尝试获取锁
              if (compareAndSetState(0, 1))
                  setExclusiveOwnerThread(Thread.currentThread());
              else
                  // 不成功的话走正常获取锁的流程,将其加入到队列排队
                  acquire(1);
          }
          // 省略部分代码...
      }
      
  6. JAVA锁(synchronized)内部实现原理,JVM的锁优化有哪些
    原理:
    synchronized在经过编译后,会在同步块的前后形成monitorentermonitorexit两个字节码命令。者两个字节码都需要一个reference类型的参数来指明需要加锁的对象(对象实例或者Class对象的)。
    并且规定synchronized是可重入的,执行monitorenter需要先尝试获取对象的锁,如果该对象未被锁定或者当前线程已经拥有该对象的锁,那么锁的计数器加一;monitorexit则相反,计数器减一,当计数器为0时锁才会被释放。

    JVM的锁优化:
    锁消除: 返现如果只有一个线程使用或者无需加锁的时候,直接消除锁
    锁粗化: 扩大加锁范围
    自旋锁: 没有获取到锁的时候自旋等待(消耗CPU),省去了线程的上下文切换;当竞争特别激烈的时候该优化不一定就好了。
    自适应锁: 在自旋锁的基础上,智能的调控自旋的次数或时间
    轻量级锁: 在没有多线程竞争的前提下,利用CAS ,减少传统的重量级锁使用操作系统互斥量产生的性能消耗
    偏向锁: 当一个线程获取锁后,在其他线程获取锁之前,该线程再次进入加锁代码块时无需再次获取锁;
    但是当有另一个线程来获取该锁时,偏向锁便不再生效。
    偏向所->轻量级锁->重量级锁

  7. 无锁并发

    // todo
    
  8. AQS的实现原理
    请看另一篇博文: JAVA并发编程: CAS和AQS

  9. volatile的理解
    volatile具有可见性和有序性,但是不具有原子性
    适用场景:
    适用于对变量的写操作不依赖于当前值,对变量的读取操作不依赖于非volatile变量。
    (eg. 通常用做某类状态标志)

    具体jvm是如何实现volatile的可参考: 《深入理解Java虚拟机 JVM高级特性与最佳实践》中将JMM的。
    12.3.3–对于volatile型变量的特殊规则

  10. JAVA线程池: ThreadPoolExecutor
    可以参考下JAVA线程池原理详解一
    主要需要了解到如下问题:

    1. 为何需要使用到线程池
    2. ThreadPoolExecutor构造函数中各属性的理解
    3. 线程池中对线程的管理,何时创建,何时回收
    4. 线程池中任务队列的类型和区别(SynchronousQueue,LinkedBlockingQueue,ArrayBlockingQueue)
    5. 几种拒绝策略的区别(AbortPolicy,CallerRunsPolicy,DiscardPolicy,DiscardOldestPolicy)
    6. 如何确定coreSize和maxSize的大小

待续

发布了37 篇原创文章 · 获赞 58 · 访问量 16万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览