-
通过 L 可以知道是否成功获得锁,S 不可以
-
L 可以提高多个线程进行读写操作的效率
========================================================================
-
可定时锁等待
-
可轮询锁等待
-
可中断锁等待
-
公平性
-
实现非块结构的加锁
-
绑定多个Condition。通过多次newCondition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步的功能.通过await(),signal();
内置锁的死锁问题只能通过重启解决,可定时、可轮询锁提供了另一种选择:
通过tryLock
解决
public class DeadlockAvoidance {
private static Random rnd = new Random();
public boolean transferMoney(Account fromAcct,
Account toAcct,
DollarAmount amount,
long timeout,
TimeUnit unit)
throws InsufficientFundsException, InterruptedException {
long fixedDelay = getFixedDelayComponentNanos(timeout, unit);
long randMod = getRandomDelayModulusNanos(timeout, unit);
long stopTime = System.nanoTime() + unit.toNanos(timeout); //定时,轮询
while (true) {
if (fromAcct.lock.tryLock()) {
try {
if (toAcct.lock.tryLock()) {
try {
if (fromAcct.getBalance().compareTo(amount) < 0)
throw new InsufficientFundsException();
else {
fromAcct.debit(amount);
toAcct.credit(amount);
return true;
}
} finally {
toAcct.lock.unlock();
}
}
} finally {
fromAcct.lock.unlock();
}
}
if (System.nanoTime() < stopTime)
return false;
NANOSECONDS.sleep(fixedDelay + rnd.nextLong() % randMod);
}
}
private static final int DELAY_FIXED = 1;
private static final int DELAY_RANDOM = 2;
static long getFixedDelayComponentNanos(long timeout, TimeUnit unit) {
return DELAY_FIXED;
}
static long getRandomDelayModulusNanos(long timeout, TimeUnit unit) {
return DELAY_RANDOM;
}
static class DollarAmount implements Comparable {
public int compareTo(DollarAmount other) {
return 0;
}
DollarAmount(int dollars) {
}
}
class Account {
public Lock lock;
void debit(DollarAmount d) {
}
void credit(DollarAmount d) {
}
DollarAmount getBalance() {
return null;
}
}
class InsufficientFundsException extends Exception {
}
}
最典型的就是阻塞的有界队列的实现。
public class BoundedBuffer {
private static final Logger logger = LoggerFactory.getLogger(BoundedBuffer.class);
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[2]; // 阻塞队列
int putptr, takeptr, count;
private void log(String info) {
logger.info(Thread.currentThread().getName() + " - " + info);
}
public void put(Object x) throws InterruptedException {
log(x + “,执行put”);
lock.lock();
log(x + “,put lock.lock()”);
try {
while (count == items.length) { // 如果队列满了,notFull就一直等待
log(x + “,put notFull.await() 队列满了”);
notFull.await(); // 调用await的意思取反,及not notFull -> Full
}
items[putptr] = x; // 终于可以插入队列
if (++putptr == items.length) {
putptr = 0; // 如果下标到达数组边界,循环下标置为0
}
++count;
log(x + “,put成功 notEmpty.signal() 周知队列不为空了”);
notEmpty.signal(); // 唤醒notEmpty
} finally {
log(x + “,put lock.unlock()”);
lock.unlock();
}
}
public Object take() throws InterruptedException {
log(“执行take”);
lock.lock();
Object x = null;
log(“take lock.lock()”);
try {
while (count == 0) {
log(“take notEmpty.await() 队列为空等等”);
notEmpty.await();
}
x = items[takeptr];
if (++takeptr == items.length) {
takeptr = 0;
}
–count;
log(x + “,take成功 notFull.signal() 周知队列有剩余空间了”);
notFull.signal();
return x;
} finally {
lock.unlock();
log(x + “,take lock.unlock()”);
}
}
public static void main(String[] args) throws InterruptedException {
final BoundedBuffer bb = new BoundedBuffer();
ExecutorService executor = Executors.newFixedThreadPool(10);
for (char i = ‘A’; i < ‘F’; i++) {
final char t = i;
executor.execute(() -> {
try {
bb.put(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
List res = new LinkedList<>();
for (char i = ‘A’; i < ‘F’; i++) {
executor.execute(() -> {
try {
char c = (char) bb.take();
res.add©;
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
try {
executor.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
logger.info(res.toString());
executor.shutdownNow();
}
}
=======================================================================
Java5的时候J.U.C的ReentrantLock锁竞争性能非常好,到了Java6使用了改进后的算法来管理内置锁,所以现在差不太多了,只好一点点
竞争性能的影响可伸缩性的关键要素:如果有越多的资源被耗费在锁的管理和线程调度上,那么应用程序得到的资源就越少,锁的实现方式越好,将需要越少的系统调用和上下文切换。
====================================================================
ReentrantLock默认创建非公平的锁,非公平指被阻塞挂起的线程(LockSupport.park)都在AQS的CLH队列中排队等待自己被唤醒。他们是按照发出的请求顺序来排队的,但一旦有一个唤醒的就会和新来的线程竞争锁,新来的可能会“插队”。若新来的成功获取锁,那么它将跳过所有等待线程而开始执行,这意味着本该被唤醒的线程失败了,对不起您回到队列的尾部继续等。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
难道这样就够了吗?不,远远不够!
提前多熟悉阿里往年的面试题肯定是对面试有很大的帮助的,但是作为技术性职业,手里有实打实的技术才是你面对面试官最有用的利器,这是从内在散发出来的自信。
备战阿里时我花的最多的时间就是在学习技术上,占了我所有学习计划中的百分之70,这是一些我学习期间觉得还是很不错的一些学习笔记
我为什么要写这篇文章呢,其实我觉得学习是不能停下脚步的,在网络上和大家一起分享,一起讨论,不单单可以遇到更多一样的人,还可以扩大自己的眼界,学习到更多的技术,我还会在csdn、博客、掘金等网站上分享技术,这也是一种学习的方法。
今天就分享到这里了,谢谢大家的关注,以后会分享更多的干货给大家!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
。
备战阿里时我花的最多的时间就是在学习技术上,占了我所有学习计划中的百分之70,这是一些我学习期间觉得还是很不错的一些学习笔记
我为什么要写这篇文章呢,其实我觉得学习是不能停下脚步的,在网络上和大家一起分享,一起讨论,不单单可以遇到更多一样的人,还可以扩大自己的眼界,学习到更多的技术,我还会在csdn、博客、掘金等网站上分享技术,这也是一种学习的方法。
今天就分享到这里了,谢谢大家的关注,以后会分享更多的干货给大家!
[外链图片转存中…(img-ZZFaaorB-1712958143184)]
[外链图片转存中…(img-pNCWLENs-1712958143185)]
[外链图片转存中…(img-4eLY3oR1-1712958143185)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-EjMrZ4YQ-1712958143185)]