理解ReentrantLock

显式锁

协调共享对象的访问的三个关键词
synchronized 、volatile和lock

Lock and ReentrantLock

内置锁的局限性:

  • 无法 中断一个正在等待获取锁的线程
  • 无法 在请求获取一个锁时 无限等待下去
  • 内置锁必须在获取该锁的代码块中释放,无法实现非阻塞结构的加锁规则

轮询锁和定时锁

同时获取两个锁时才进行操作
显式地索取和释放锁,那么在索取锁的时候可以设定一个超时时间,如果超过这个时间还没索取到锁,则不会继续堵塞而是放弃此次任务。
tryLock时设置

1
2
3
4
5
6
7
8
9
10
11
12
13
public boolean trySendOnSharedLine(String message,  
long timeout, TimeUnit unit)
throws InterruptedException {
long nanosToLock = unit.toNanos(timeout)
- estimatedNanosToSend(message);
if (!lock.tryLock(nanosToLock, NANOSECONDS))
return false;
try {
return sendOnSharedLine(message);
} finally {
lock.unlock();
}
}

可中断的锁获取操作

lock.lockInterruptibly();
能够在获取锁的同时保持对中断的响应,tryLock同样也能响应中断,适用于实现 一个定时和可中断的锁获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public boolean sendOnSharedLine(String message)
throws InterruptedException {
lock.lockInterruptibly();
try {
return cancellableSendOnSharedLine(message);
} finally {
lock.unlock();
}
}

private boolean cancellableSendOnSharedLine(String message) throws InterruptedException {
/* send something */
return true;
}

非块结构的加锁(非阻塞?)

  • 内置锁是基于块结构的加锁
  • 锁分段技术,不同的线程可以独立的对链表的不同部分进行操作。
    每个节点的锁将保护链接指针以及该节点中存储的数据,遍历或者修改时,获取当前节点的锁,直到获得下个节点的锁。
    连锁式加锁

公平性

非公平锁和公平锁,非公平锁允许插队。插队是指 当一个线程请求非公平锁时,在发出请求的同时该锁的状态变为可用,那么可跳过队列中所有等待线程。

如何选择synchronized和ReentrantLock

在一些内置锁无法满足的情况下,ReentrantLock可以作为一种高级工具:
实现 可定时、可轮询和可中断的锁获取操作,公平队列,非块结构的锁。
否则优先使用synchronized。

读-写锁

放宽粒度 允许读-读操作,多个线程同时读。
读数据时确保读取最新数据,读数据时不会又其他线程修改数据。

您的支持将鼓励我继续创作 笔芯