java多线程

线程概述

1.线程的状态

  • NEW:新建的线程,尚未执行

  • Runnable:运行中的线程,正在执行run方法

  • Blocked:阻塞等待,因某些操作被阻塞而挂起

  • Waiting:运行中的线程,因为某些操作在等待中

  • TimeWaiting:超时等待,因为执行sleep()方法正在计时等待

  • Terminated:线程已终止 调用interrupt()方法,可以中断方法

  • blocked和waiting的区别

    • block状态是线程阻塞在进入synchronized修饰的方法或代码块时的状态。
    • waiting可以通过object.join(),wait()方法达到,表示等待object线程结束,
    • block状态是处于wait状态线程的必经之路
  • stop和interrupt的区别?

    • interrupt触发异常,线程可以无视这个通知
    • stop直接终止线程,并释放锁

线程协调问题

多线程协调原则

当条件不满足时,线程进入等待状态;当条件满足时,线程被唤醒,继续执行任务

  • 使用this.wait()进入等待状态,wait()方法必须在当前获取的锁对象上调用,只有在synchronized块中才能调用wait,wait方法在调用后会释放锁
  • this.notifyAll(); // 唤醒在this锁等待的线程
  • 已唤醒的线程还需要重新获得锁后才能继续执行

ReentrantLock

java.util.concurrent.locks包提供的ReentrantLock用于替代synchronized加锁

private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
await()会释放当前锁,进入等待状态;
signal()会唤醒某个等待线程;
signalAll()会唤醒所有等待线程;
唤醒线程从await()返回后需要重新获得锁。

ReadWriteLock

  • ReadWriteLock可以提高读取效率:
  • ReadWriteLock只允许一个线程写入;
  • ReadWriteLock允许多个线程在没有写入时同时读取;
  • ReadWriteLock适合读多写少的场景。

StampedLock

  • 提供了乐观读锁,可取代ReadWriteLock以进一步提升并发性能

Atomic类

使用java.util.concurrent.atomic提供的原子操作可以简化多线程编程:

  • 原子操作实现了无锁的线程安全;
  • 适用于计数器,累加器等。

关键字

volatile

用于线程间共享的变量,
告诉虚拟机,每次访问变量时,总是获取主内存的最新值;每次修改变量后,立刻回写到主内存。关键字解决的是可见性问题:当一个线程修改了某个共享变量的值,其他线程能够立刻看到修改后的值

synchronized

修饰方法时,锁住的是整个对象

可重入锁

获取锁的时候,获取锁的记录次数+1,退出时-1,直到等于0,才时真正的释放锁

死锁

一个线程获取锁后,再继续获取另外一个锁,这个锁被另一个线程获取过,就会造成死锁,没有任何机制能解除死锁,只能强制结束JVM进程,

避免死锁的方式就是获取锁的顺序要一致

CAS:

  • Compare and Set 底层也是java调用汇编指令进行锁的操作
public int incrementAndGet(AtomicInteger var) {
    int prev, next;
    do {
        prev = var.get();
        next = prev + 1;
    } while ( ! var.compareAndSet(prev, next));
    return next;
}
在这个操作中,如果AtomicInteger的当前值是prev,那么就更新为next,返回true。如果AtomicInteger的当前值不是prev,就什么也不干,返回false。通过CAS操作并配合do ... while循环,即使其他线程修改了AtomicInteger的值,最终的结果也是正确的。
原文地址:https://www.cnblogs.com/rise0111/p/13565910.html