Java并发编程原理 - Unsafe && LockSupport类及AQS同步器的设计

[相关源码]

(https://github.com/Wasabi1234/Java-Concurrency-Progamming-Tutorial)

1 Unsafe类的park和unpark

publicnativevoidpark(boolean var1, long var2);publicnativevoidunpark(Object var1);
park方法用来阻塞一个线程,第一个参数用来指示后面的参数是绝对时间还是相对时间,true表示绝对时间,false表示从此刻开始后的相对时间.调用park的线程就阻塞在此处.
unpark用来释放某个线程的阻塞,线程用参数var1表示
举个例子:

2 LockSupport

直接使用Unsafe还是有诸多不便之处,因此lock包提供了一个辅助类LockSupport封装了park和unpark

举个例子:

可以看出,使用LockSupport要比直接只用Unsafe更加便捷。

此外,LockSupport还可以用来给线程设置一个Blocker对象,便于调试和检测线程,其原理是使用Unsafe的putObject方法直接设置Thread对象的parkBlocker属性,并在合适的时候读取这个Blocker对象,例子如下:

3 AQS同步器

各种锁ReentrantLock、ReentrantReadWriteLock以及各种同步器诸Semaphore、CountDownLatch等,核心都是AbstractQueuedSynchronizer

要真正从源头理解AQS,建议仔细阅读该类的设计者的论文 (http://gee.cs.oswego.edu/dl/papers/aqs.pdf)3.1 使用 AQS 手写排它锁让我们先具体感知它是如何使用的。
这里有一个非常简单的例子SimpleLock,实现了一个最简单的排它锁。

当有线程获得锁时,其他线程只能等待
当这个线程释放锁时,其他线程可以竞争获取锁

运行结果表明,通过简单的几行代码,就实行了一个锁的所有功能。

根据JUC作者的建议,AQS的使用方法要遵循上面这个模式。

使用一个内部类Sync来继承AQS,并实现AQS的相关方法

一般是

tryAcquire
tryRelease(排它锁)
或者

tryAcquireShared
tryReleaseShared(共享锁)
在内部使用代理模式实现锁的功能

这样可以让暴露出的同步、互斥方法名由程序员自行决定。例如各种锁可以使用

lock
unlock
Semaphore可以使用

acquire
release
CountDownLatch可以使用

await
countDown
2 AQS基本原理

要实现一个同步器,需要三个条件:

一个同步状态值,且可原子操作该状态值.显然CAS胜任
阻塞线程和解除阻塞线程的机制,可以用LockSupport来实现
维护一个阻塞线程的队列,并在队列的每个节点中存储线程的状态等信息
让我们看看AQS又是如何设计满足的这三个条件。

2.1 状态值及相应的操作方法

privatevolatileint state;protectedfinalintgetState(){return state;}protectedfinalvoidsetState(int newState){ state = newState;}protectedfinalbooleancompareAndSetState(int expect, int update){// See below for intrinsics setup to support thisreturn unsafe.compareAndSwapInt(this, stateOffset, expect, update);}state 为 volatile int型,它的CAS方法,提供原子的比较更新操作。

一般,AQS认为

state == 0 时,同步器处于释放状态,多线程此时可竞争获取同步器
state ≠ 0 时,同步器处于已获取状态,后续线程需进入队列,等待同步器(可重入同步器允许获取同步器的线程再次进入该同步器,此时使用state计数)
当然,很多情况下,程序员也可自己定义state的值的含义,特别是在实现读写锁时,需要将state一分为二的用。
2.2 阻塞和解除阻塞

LockSupport 提供了阻塞和解除阻塞的功能。因此,所有同步器的阻塞操作其实都是基于LockSupport的,也就是基于Unsafe的park和unpark方法的。

2.3 线程等待队列

AQS内部提供了一个Node类型,它是用来形成“线程等待队列”的节点类型,以及一个由Node类型组成的队列。转自 http://www.learnfuture.com/Java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值