请问 java并发包中的 Thread exclusiveOwnerThread 为什么用 transient 修饰?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请问 java并发包中的 Thread exclusiveOwnerThread 为什么用 transient 修饰?相关的知识,希望对你有一定的参考价值。

并发抽象类 AbstractOwnableSynchronizer 中的当前线程的拥有者为啥要用 transient 关键字修饰?

参考技术A FixedThreadPool模式会使用一个优先固定数目的线程来处理若干数目的任务。规定数目的线程处理所有任务,一旦有线程处理完了任务就会被用来处理新的任务(如果有的话)。这种模式与上面的CachedThreadPool是不同的,CachedThreadPool模式下处理一定数量的任务的线程数目是不确定的。而FixedThreadPool模式下最多的线程数目是一定的。采用FixedThreadPool模式编写客户端程序如下:packagenet.jerryblog.concurrent;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassFixedThreadPoolpublicstaticvoidmain(String[]args)//三个线程来执行五个任务ExecutorServiceexec=Executors.newFixedThreadPool(3);for(inti=0;i<5;i++)exec.execute(newLiftOff());exec.shutdown();3.SingleThreadExecutor模式SingleThreadExecutor模式只会创建一个线程。它和FixedThreadPool比较类似,不过线程数是一个。如果多个任务被提交给SingleThreadExecutor的话,那么这些任务会被保存在一个队列中,并且会按照任务提交的顺序,一个先执行完成再执行另外一个线程。SingleThreadExecutor模式可以保证只有一个任务会被执行。这种特点可以被用来处理共享资源的问题而不需要考虑同步的问题。SingleThreadExecutor模式编写的客户端程序如下:packagenet.jerryblog.concurrent;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassSingleThreadExecutorpublicstaticvoidmain(String[]args)ExecutorServiceexec=Executors.newSingleThreadExecutor();for(inti=0;i<2;i++)exec.execute(newLiftOff());这种模式下执行的结果如下:#0(9)#0(8)#0(7)#0(6)#0(5)#0(4)#0(3)#0(2)#0(1)#0(LiftOff!)第一个任务执行完了之后才开始执行第二个任务。

Java并发包中的并发队列简记

ConcurrentLinkedQueue

ConcurrentLinkedQueue内部的队列使用带头节点的单向链表实现,并且维持头尾两个指针,头指针出队、尾指针入队。该队列的出队入队操作都是线程安全的。

保证安全的方式

对于头尾指针均使用volatile关键字修饰从而保证可见性,对于头尾指针的修改使用CAS操作保证了原子性。所以对于出入队是线程安全的。

主要方法

offer:入队操作

add:添加元素,内部通过调用offer实现

poll:出队操作,删除队头元素并返回

peek:获取对头元素,不删除结点

size:返回队列的大小,由于队列没有加锁,返回结果可能不准确,在返回时队列有可能被其它线程修改

remove:删除队列中指定的元素,有多个满足的元素时删除第一个

contains:判断是否包含某个元素,和size一样的原因,导致结果也可能不准确

LinkedBlockingQueue

LinkedBlockingQueue同样使用单向链表,并且维持头尾两个指针,另外使用了一个原子变量count来记录当前队列的结点数量。

保证线程安全的方式

对于出队和入队分别设置了takeLock和putLock两个独占锁,保证同一时刻只有一个线程可以进行出队或者入队操作,另外使用notEmpty和notFull两个条件变量用于存由于放入队和出队阻塞的线程。

主要方法

offer:非阻塞的入队操作,如果没有空间,则直接丢弃入队的元素返回false

put:阻塞的入队操作,如果没有空间,就把当前线程放入notFull的条件队列中,并且在获取锁时可相应中断

poll:非阻塞的出队操作,如果队列为空则直接返回false

peek:获取对头元素,不删除队头,该操作也是非阻塞的

take:阻塞的出队操作,如果队列为空,则线程被放入notEmpty条件队列中,并且在获取锁时可相应中断

remove:删除队列指定的元素

size:获取队列的大小,通过count原子变量获取,由于出对入队均加锁,所以结果是准确的

ArrayBlockingQueue

ArrayBlockingQueue与LinkedBlockingQueue的具体操作基本一致,不同点在于ArrayBlockingQueue底层是使用数组实现的循环队列,另外关于加锁方面ArrayBlockingQueue对出队和入队使用的是同一个锁,锁的粒度比LinkedBlockingQueue大,在获取size时ArrayBlockingQueue需要加锁获取,因为count使用的是普通变量。

以上是关于请问 java并发包中的 Thread exclusiveOwnerThread 为什么用 transient 修饰?的主要内容,如果未能解决你的问题,请参考以下文章

深入浅出Java并发包—锁机制

java-- java并发包总结

Java学习笔记—多线程(java.util.concurrent并发包概括,转载)

Java高级部分知识总结快速进阶

Java并发包中的线程同步器

(41)java并发包中的线程池种类及特性介绍