youyichannel

志于道,据于德,依于仁,游于艺!

0%

死锁

以下内容偏理论,面试可参考

死锁产生的四个必要条件

  1. 互斥:资源必须处于非共享模式,即一次只有一个进程可以使用。如果另一进程申请该资源,那么必须等待直到该资源被释放为止。
  2. 占有并等待:一个进程至少应该占有一个资源,并等待另一资源,而该资源被其他进程所占有。
  3. 非抢占:资源不能被抢占。只能在持有资源的进程完成任务后,该资源才会被释放。
  4. 循环等待:有一组等待进程 {P0, P1,..., Pn}P0 等待的资源被 P1 占有,P1 等待的资源被 P2 占有,……,Pn-1 等待的资源被 Pn 占有,Pn 等待的资源被 P0 占有。
阅读全文 »

Synchronized锁升级 —— 轻量级锁升级为重量级锁

轻量级锁 到 重量级锁:释放锁(1~4)并唤醒等待线程

  1. 线程1初始化Monitor对象
  2. 将状态设置为碰撞中(inflating)
    阅读全文 »

Synchronized锁升级 —— 轻量级锁加锁与解锁

1)轻量级锁加锁

线程在执行同步代码块之前,JVM会先在当前线程的栈帧中创建存储锁记录的空间(Lock Record 记录),并将对象头中的Mark Word(前30位:25位的hashcode,4位的分代年龄,1位是否是偏向锁标志)复制到锁记录中,官方称之为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针(指向线程栈帧中Lock Record的指针),如果成功,当前线程获得锁;如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。

2)轻量级锁解锁

轻量级锁解锁时,会使用原子的CAS操作将Displaced Mark Word(Lock Record 记录)替换到对象头中,如果成功,则表示没有竞争发生;如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。

阅读全文 »

《MySQL是怎样运行的 —— 从跟上理解MySQL》—— 第七章

InnoDB存储引擎B+树索引结论:

  • 每个索引都对应一棵B+树。B+树分为好多层,最下边一层是叶子节点,其余的是内节点。所有用户记录都存储在 B+树的叶子节点,所有目录项记录都存储在内节点。
  • InnoDB存储引擎会自动为主键建立聚簇索引(如果没有显式指定主键或者没有声明不允许存储NUUL的UNIQUE键,它会自动添加主键,即6字节的隐藏列row_id),聚簇索引的叶子节点包含完整的用户记录。
  • 可以为必要的列建立二级索引,二级索引的叶子节点包含的用户记录由索引列和主键组成。如果想通过二级索引查找完整的用户记录,需要执行回表操作。
  • B+树中的每层节点都按照索引列的值从小到大的顺序排序组成了双向链衰,而且每个页内的记录(无论是用户记录还是目录项记录)都按照索引列的值从小到大的顺序形成了一个单向链表。如果是联合索引,则页面和记录先按照索引列中前面的列的值排序;如果该列的值相同,再按照索引列中后面的列的值排序。
  • 通过索引查找记录时,是从B+树的根节点开始一层一层向下搜索的.由于每个页面(无论是非叶子节点页面还是叶子节点页面)中的记录都划分成了若干个组,每个组中索引列值最大的记录在页内的偏移量会被当作槽依次存放在页目录中,因此可以在页目录中通过二分法快速定位到索引列等于某个值的记录。
阅读全文 »

Synchronized锁升级 —— 偏向锁的撤销

偏向锁状态变化与最终升级为轻量级锁:

  1. A线程获取偏向锁成功,已经退出执行不再是活跃线程;B线程来获取偏向锁,默认前20次直接升级为轻量级锁
  2. A线程获取偏向锁成功,已经退出执行不再是活跃线程;B线程来获取偏向锁,默认20次以后,对象锁偏向线程B。达到40次阈值后,若再有其他线程(比如线程C)过来争抢,则触发批量撤销,该对象不再有任何偏向锁的情况。
阅读全文 »

《MySQL是怎样运行的 —— 从跟上理解MySQL》—— 第六章

一、没有索引时的进行查找

没有索引的时候是如何查找记录的?以精确匹配来举例:

SELECT [列名列表] FROM 表名 WHERE 列名 = xxx;

1.1 在一个页中查找

假设目前表中的记录比较少,所有的记录都可以被存放到一个页中,在查找记录的时候可以根据搜索条件的不同分为两种情况:

  • 以主键为搜索条件:在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录。
  • 以其他列作为搜索条件:由于没有建立所谓的页目录,这种情况下只能从最小记录开始依次遍历单链表中的每条记录,然后对比每条记录是不是符合搜索条件。查找效率低下。

1.2 在很多页中查找

大部分情况下表中的记录是非常多的,需要很多数据页来存储这些记录。在很多页中查找记录分为两个步骤:

  • 定位到记录所在的页
  • 从所在的页内查找相应的记录

在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,在每一个页中根据上述查找方式去查找指定的记录。因为要遍历所有的数据页,所以这种方式显然是超级耗时的。

怎么解决?

使用索引

阅读全文 »

Synchronized锁升级 —— 偏向锁的撤销(非必需)

示例代码1:

启动前配置JVM参数:-XX:BiasedLockingStartupDelay=0

阅读全文 »