LIXI.FUN
0%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ArrayBlockingQueue<E> {

/** Main lock guarding all access */
final ReentrantLock lock;

public E take() throws InterruptedException {
// 就是下面这行,为什么要把 this.lock 赋值给一个本地 final 变量
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
}

It’s an extreme optimization Doug Lea, the author of the class, likes to use. Here’s a post on a recent thread on the core-libs-dev mailing list about this exact subject which answers your question pretty well.

stackoverflow - arrayblockingqueue-why-copy-final-memever-field-into-local-final-variable

It’s a coding style made popular by Doug Lea.
It’s an extreme optimization that probably isn’t necessary;
you can expect the JIT to make the same optimizations.
(you can try to check the machine code yourself!)
Nevertheless, copying to locals produces the smallest
bytecode, and for low-level code it’s nice to write code
that’s a little closer to the machine.

Also, optimizations of finals (can cache even across volatile
reads) could be better. John Rose is working on that.

For some algorithms in j.u.c,
copying to a local is necessary for correctness.

Performance of locally copied members ?

极致优化,让编译器(本地编译器或者 JIT)更有可能把后续对堆上同一个地址的访问”优化”成对栈上比较近的地址或寄存器的访问。

不知道有没有人跟我有一样的疑问”大量请求涌入为什么会把服务搞挂掉?”

有线程池的存在,不是限制了进程能占用的系统资源么?为什么会挂掉呢?

所以问题就出在,这个挂掉,具体指的是什么意思么?进程的崩溃吗?

阅读全文 »

如果百度得到的答案,扯到了因为单线程,没有多线程的上下文切换锁之类的所以快的,还有 epoll 之类的,不用看了又是一篇复制粘贴的文章,因为 epoll 首要解决的问题就不是快,具体可以看 IO 多路复用解决的啥问题,ps: 现在,最新版的 redis (6.x) 开始用多线程来处理 IO 了。

Redis 快的主要原因:

  1. 纯内存操作
  2. 数据结构简单高效

benchmark 里的每秒增删改查的数字大,是因为单次操作耗时少,这个叫快,而数据量大,叫多。

首先抛出一个问题:C10K 问题是个什么问题?

从整个系统的服务能力来看 C10K 首先是一个关于连接,尤其是长连接的问题,只是高并发的一个前置条件,即一个进程支持大量连接的问题,接入连接之后的是否能够提供服务是另一个问题了。

IO 多路复用,解决的也就是这个前置条件,关于一个进程维持大量连接这件事儿。

对于近几年从业的小伙伴来说,不知道会不会有我一样的疑问,为什么说 BIO 的时候,就提到一个连接一个线程,他们就不会用线程池吗?

阅读全文 »

  1. new 是个多指令的非原子操作
  2. 使用了 synchronized 包裹的块代码是块与块之间的最终行为表现是有序确定的,但在线程内部是否存在指令重排(无序)是不确定的
  3. 第一个 if 并未在 synchronized 里面,所以另一个线程可能拿到一个因 synchronized 块内部的指令重排导致的未完全初始化的对象(先分配地址,后初始化,但外部线程看已经不为 null 了)
    阅读全文 »