分布式锁
1、什么是锁?
2、锁解决什么问题?
3、单机版的锁怎么实现的?
synchronized
- wait
- notify
ReentrantLock
- lock
- unlock
操作系统层面
- 公平锁:管程ReentrantLock(就是AQS);AtomicInteger没有管程,里面是自旋锁
- 非公平锁
4、分布式锁怎么实现的?
- OSI 是概念性的模型,实际上是 TCP / IP 四层协议
- 多机版分布式锁 = 单机版的线程同步模型 + ICP / IP 协议栈
- 总线协议
(例如 lock cmpxchg)
+ 数据,管程 = 单机版锁
什么?你不知道lock cmpxchg
?
来,看一下 Unsafe.java 类的源码:
这是在 package sun.misc;
包下,JDK1.8 的 OpenJDK 的源码
// The following contain CAS-based Java implementations used on
// platforms not supporting native instructions
/**
* Atomically adds the given value to the current value of a field
* or array element within the given object <code>o</code>
* at the given <code>offset</code>.
*
* @param o object/array to update the field/element in
* @param offset field/element offset
* @param delta the value to add
* @return the previous value
* @since 1.8
*/
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
这里面的 getAndAddInt()
方法的实现,调用了 compareAndSwapInt()
方法,这是一个 native 方法
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
*/
public final native boolean compareAndSwapInt(Object o, long offset,
int expected,
int x);
在 HotSpot 源码中是 C++ 的
内联汇编:
cmp $0, " #mp ";
je 1f;
lock; 1:
- lock 是锁总线
- 状态寄存器
位置:
openjdk-8-src-b132-03_mar_2014\openjdk\hotspot\src\os_cpu\linux_x86\vm\atomic_linux_x86.inline.hpp
// Adding a lock prefix to an instruction on MP machine
#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "
inline jint Atomic::add (jint add_value, volatile jint* dest) {
jint addend = add_value;
int mp = os::is_MP();
__asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)"
: "=r" (addend)
: "0" (addend), "r" (dest), "r" (mp)
: "cc", "memory");
return addend + add_value;
}
分布式锁的实现
基于 Redission 对 Redis 分布式锁的实现:
在 Redission 源码中,是使用 lua 脚本 + redis 实现锁重入: