Blog

Spectral Theorem(谱定理)

Content #

对称矩阵S可对角化成下列形式: \[S=Q\Lambda Q^{-1}=Q\Lambda Q^T\] real eigenvalues in \(\Lambda\), and orthonormal eigenvectors in the columns of Q.

From #

伪共享(False Sharing)问题

Content #

除了写屏障的开销外,卡表在高并发场景下还面临着“伪共享”(False Sharing)问题。什么是“伪共享”(False Sharing)问题?

伪共享是处理并发底层细节时一种经常需要考虑的问题,现代中央处理器的缓存系统中是以缓存行(Cache Line)为单位存储的,当多线程修改互相独立的变量时,如果这些变量恰好共享同一个缓存行,就会彼此影响(写回、无效化或者同步)而导致性能降低,这就是伪共享问题。

假设处理器的缓存行大小为64字节,由于一个卡表元素占1个字节,64个卡表元素将共享同一个缓存行。这64个卡表元素对应的卡页总的内存为32KB(64×512 字节),也就是说如果不同线程更新的对象正好处于这32KB的内存区域内,就会导致更新卡表时正好写入同一个缓存行而影响性能。

From #

抢先式中断(Preemptive Suspension)和主动式中断(Voluntary Suspension)

Content #

HotSpot也的确没有为每条指令都生成OopMap,前面已经提到,只是在“特定的位置”记录了这些信息,这些位置被称为安全点(Safepoint)。对于安全点,另外一个需要考虑的问题是,如何在垃圾收集发生时让所有线程(这里其实不包括执行JNI调用的线程)都跑到最近的安全点,然后停顿下来。有哪两种方案可供选择?

抢先式中断不需要线程的执行代码主动去配合,在垃圾收集发生时,系统首先把所有用户线程全部中断,如果发现有用户线程中断的地方不在安全点上,就恢复这条线程执行,让它一会再重新中断,直到跑到安全点上。现在几乎没有虚拟机实现采用抢先式中断来暂停线程响应GC事件。

而主动式中断的思想是当垃圾收集需要中断线程的时候,不直接对线程操作,仅仅简单地设置一个标志位,各个线程执行过程时会不停地主动去轮询这个标志,一旦发现中断标志为真时就自己在最近的安全点上主动中断挂起。轮询标志的地方和安全点是重合的,另外还要加上所有创建对象和其他需要在Java堆上分配内存的地方,这是为了检查是否即将要发生垃圾收集,避免没有足够内存分配新对象。

From #

getDeclaredConstructors vs. getConstructors

Content #

Java Class类中的getDeclaredConstructors and getConstructors这两个方法之间的区别是什么?

  1. getDeclaredConstructors (when you want all the constructors)
  2. getConstructors (when you want only public constructors)

From #

clinit方法

Content #

Java编译器生成的clinit方法中包含哪些内容?

  1. 除常量值初始化之外的直接赋值操作
  2. 所有静态代码块中的代码

From #

重新封装RedisDistributedLock上锁的逻辑

Content #

Java中有Transaction类定义如下:

public class Transaction {
  // ...fields
  // ...get() methods...
  // ...contructor

  public boolean execute() throws InvalidTransactionException {
    boolean isLocked = false;
    try {
      isLocked = RedisDistributedLock.getSingletonIntance().lockTransction(id);
      if (!isLocked) {
        return false; // 锁定未成功,返回false,job兜底执行
      }
      //...
    } finally {
      if (isLocked) {
       RedisDistributedLock.getSingletonIntance().unlockTransction(id);
      }
    }
  }
}

现在要对execute方法做单元测试,由于RedisDistributedLock 是一个单例类,单例相当于一个全局变量,无法 mock(无法继承和重写方法),也无法通过依赖注入的方式来替换。

可以对 transaction 上锁这部分逻辑重新封装一下。具体代码实现如下所示:

public class TransactionLock {
  public boolean lock(String id) {
    return RedisDistributedLock.getSingletonIntance().lockTransction(id);
  }

  public void unlock() {
    RedisDistributedLock.getSingletonIntance().unlockTransction(id);
  }
}
public class Transaction {
  //...
  private TransactionLock lock;

  public void setTransactionLock(TransactionLock lock) {
    this.lock = lock;
  }

  public boolean execute() {
    //...
    try {
      isLocked = lock.lock();
      //...
    } finally {
      if (isLocked) {
        lock.unlock();
      }
    }
    //...
  }
}

针对重构过的代码,单元测试代码修改为下面这个样子。

...

SafeVarargs注解的使用限制

Content #

只能应用于构造器,或由static或final或private限定的方法。在任何可能会被覆盖的方法上使用该注解都是没有意义的。

From #

sub:git

Content #

Cookbook #

  • 将本地分支与远程分支关联

    git branch --set-upstream-to=origin/master master
    
  • 比较bug和tree分支中remember文件的差异

    git diff bug tree remember
    
  • 检出并切换到远程分支

    git checkout -b test origin/test
    git checkout -t origin/test