进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源
线程:CPU调度的最小单位,必须依赖进程而存在。
两种方法:继承类Thread
实现接口 Runnable
为什么要类,也要接口。因为JAVA单继承,类只能继承一个
接口 Callable 与Runnable 区别:Callable 有返回值
线程自然终止:自然执行完或抛出未处理异常
stop(),resume(),suspend()已不建议使用,stop()会导致线程不会正确释放资源,suspend()不释放资源容易导致死锁。
java线程是协作式,而非抢占式
调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。
isInterrupted() 判定当前线程是否处于中断状态。
static方法interrupted() 判定当前线程是否处于中断状态,同时中断标志位改为false。
方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()。
所有阻塞方法都会抛出InterruptedException
新建线程调用start()方法进入就绪状态,cpu分配或join()方法获取执行权进入运行状态,调用sleep()或wait()进入阻塞状态,sleep时间到或调用notify,notifyAll方法进入就绪状态,运行时还可以调用yield方法让步进入就绪状态进行重新争抢cpu
线程在执行yield()以后,持有的锁是不释放的
sleep()方法被调用以后,持有的锁是不释放的
调动方法之前,必须要持有锁。调用了wait()方法以后,锁就会被释放,当wait方法返回的时候,线程会重新持有锁
调动方法之前,必须要持有锁,调用notify()方法本身不会释放锁的
和主线程共死,finally不能保证一定执行
在start之前setDaemon(true);设置守护线程,主线程运行完,子线程也结束。
对象锁,锁的是类的对象实例。
类锁 ,锁的是每个类的的Class对象,每个类的的Class对象在一个虚拟机中只有一个,所以类锁也只有一个。
适合于只有一个线程写,多个线程读的场景,因为它只能确保可见性。
线程变量。可以理解为是个map,类型 Map<Thread,Integer>
作用:是一组线程等待其他的线程完成工作以后在执行,加强版join
await用来等待,countDown负责计数器的减一
让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行CyclicBarrier(int parties)
控制同时访问某个特定资源的线程数量,用在流量控制
两个线程间的数据交换
CAS(Compare And Swap),指令级别保证这是一个原子操作
基本思路:如果地址V上的值和期望的值A相等,就给地址V赋给新值B,如果不是,不做任何操作。
synchronized jvm级别的锁,代码简洁,Lock:Java语言级别的锁,获取锁可以被中断,超时获取锁,尝试获取锁,读多写少用读写锁
如果在时间上,先对锁进行获取的请求,一定先被满足,这个锁就是公平的,不满足,就是非公平的
非公平的效率一般来讲更高
节约了从挂起(排队)到拿锁的时间
AbstractQueuedSynchronizer
实质上用双向链表实现同步队列
用AQS实现同步,首先线程获取同步状态失败时,生成note节点加入同步队列尾部(用CAS设置),判断前驱是否为首节点,是的话尝试获取同步状态,获取成功将其设置为首节点,获取不成功进入等待队列,再去尝试获取同步状态
竞争失败的线程会打包成Node放到同步队列
注:AQS实质上拥有一个同步队列和多个等待队列,具体对应关系如下图所示:
上边为同步队列 双向链表
下边为condition等待队列 单向链表
Await从同步队列移动到等待队列等待
Signal从等待队列移动到同步队列争抢锁
1.7及之前: ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment实际继承自可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,每个Segment里包含一个HashEntry数组,我们称之为table,每个HashEntry是一个链表结构的元素。
1.8
1、 取消了segment数组,直接用table保存数据,锁的粒度更小,减少并发冲突的概率。
2、 存储数据时采用了链表+红黑树的形式,纯链表的形式时间复杂度为O(n),红黑树则为O(logn),性能提升很大。什么时候链表转红黑树?当key值相等的元素形成的链表中元素个数超过8个的时候。
Node类存放实际的key和value值,hash ,next
sizeCtl:
负数:表示进行初始化或者扩容,-1表示正在初始化,-N,表示有N-1个线程正在进行扩容
正数:0 表示还没有被初始化,>0的数,初始化或者是下一次进行扩容的阈值
TreeNode 用在红黑树,表示树的节点, TreeBin是实际放在table数组中的,代表了这个红黑树的根。
答:用于存储键值对数据的HashEntry,在设计上它的成员变量value等都是volatile类型的,这样就保证别的线程对value值的修改,get方法可以马上看到。
答:ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,只要多个修改操作发生在不同的段上,它们就可以并发进行。
原文:https://www.cnblogs.com/XjhQdl/p/10665249.html