分析完了AQS原理,下面借助AQS实现一个同步类,然后用这个同步类写一下经典的三个线程循环打印。就决定叫它BLock
。
对于BLock
而言只需要对外提供两个方法lock()
、unlock()
,那么AQS的具体实现可以模仿ReentrantLock
托管给内部类Sync
。
class BLock {
private val sync = Sync()
fun lock() {
sync.lock()
}
fun unlock() {
sync.unlock()
}
private inner class Sync : AbstractQueuedSynchronizer() {
fun lock() = acquire(1)
override fun tryAcquire(arg: Int): Boolean {
return true
}
fun unlock() {
release(1)
}
override fun tryRelease(arg: Int): Boolean {
return true
}
}
}
lock()默认请求一个资源acquire(1)
;unlock()对应释放资源release(1)
。接下来分别实现tryAcquire()
、tryRelease()
实现资源控制,也就是state
的值啦。
tryAcquire()
override fun tryAcquire(arg: Int): Boolean {
val s = state
if (s == 0) {
if (compareAndSetState(0, arg)) {
exclusiveOwnerThread = currentThread
return true
}
}
return false
}
获取当前state:
- 为0表示锁已被释放,cas改为1成功后标识currentThread然后返回true
- 其它情况下返回false
但是这样忽略了可重入的逻辑,有可能当前线程持有了锁又再次获取锁,问题不大加个if else
override fun tryAcquire(arg: Int): Boolean {
val currentThread = Thread.currentThread()
val s = state
if (s == 0) {
if (compareAndSetState(0, arg)) {
exclusiveOwnerThread = currentThread
return true
}
} else if (currentThread === exclusiveOwnerThread) {
val next = s + arg
state = next
return true
}
return false
}
state为1时判断当前线程是否已经获取了锁currentThread === exclusiveOwnerThread
,已获取state继续+1,由此可知lock()了几次unlock()也要对应调用才能释放锁。
tryRelease()
override fun tryRelease(arg: Int): Boolean {
val c: Int = state - arg
if (Thread.currentThread() !== exclusiveOwnerThread) throw IllegalMonitorStateException()
var free = false
if (c == 0) {
free = true
exclusiveOwnerThread = null
}
state = c
return free
}
state减去1
- check当前线程是否获取了锁
- state为0释放锁,currentThread置为null
- state不为0返回false
写下来其实和ReentrantLock非公平锁的实现差不太多,接下来用BLock实现三个线程循环打印。
private fun initThread() {
val lock = BLock()
var count = 0
val maxCount = 100
Thread A@{
while (true) {
lock.lock()
if (count > maxCount) {
lock.unlock()
return@A
}
if (count % 3 == 0) {
Log.d("chenxuan----->", "A-$count")
count++
}
lock.unlock()
}
}.start()
Thread B@{
while (true) {
lock.lock()
if (count > maxCount) {
lock.unlock()
return@B
}
if (count % 3 == 1) {
Log.d("chenxuan----->", "B-$count")
count++
}
lock.unlock()
}
}.start()
Thread C@{
while (true) {
lock.lock()
if (count > maxCount) {
lock.unlock()
return@C
}
if (count % 3 == 2) {
Log.d("chenxuan----->", "C-$count")
count++
}
lock.unlock()
}
}.start()
}
check下log
log.png
网友评论