1 Overview
Linux内核中常见的同步机制有Atomic Operation,Spin Locks,Semaphore,Mutex等。其中Spin Locks和Semaphore都支持读/写锁。此外,Linux内核还支持一种更轻量级的读/写锁定机制:Sequential Lock。跟其它读/写锁定机制相比,Sequential Lock有以下特点:
- 在获取锁时偏向写锁。只要他人不持有写锁,那么获得写锁的操作总是能够成功。
- 读操作时不需要获得锁(即读操作永远不会被阻塞),然而在有些情况下读操作需要重试。
- Sequential Lock更轻量级,可伸缩性相对更好。
2 Linux Kernel's Implementation
以下是2.6版本的内核中,Sequential Lock的实现:
typedef struct {
unsigned sequence;
spinlock_t lock;
} seqlock_t;
static inline void write_seqlock(seqlock_t *sl)
{
spin_lock(&sl->lock);
++sl->sequence;
smp_wmb();
}
static inline void write_sequnlock(seqlock_t *sl)
{
smp_wmb();
sl->sequence++;
spin_unlock(&sl->lock);
}
static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
{
unsigned ret = sl->sequence;
smp_rmb();
return ret;
}
static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
{
smp_rmb();
return (iv & 1) | (sl->sequence ^ iv);
}
以上代码中,通过使用spin lock保证了write操作的原子性。需要注意的是,Linux spin lock是非可重入锁,这也是read_seqretry方法中可以通过(iv & 1)判断一个写操作是否正在进行中的原因。此外,Linux spin lock只能保证原子性,为了避免由于编译器或者处理器对指令的重排序(例如x86平台不会对写操作重排序,但是可能会对读操作进行重排序)所导致的潜在问题,seqlock使用memory barrier(smp_wmb和smp_rmb)保证了内存可见性。
seqlock的用法如下:
To define a seqlock:
seqlock_t mr_seq_lock = DEFINE_SEQLOCK(mr_seq_lock);
The write path:
write_seqlock(&mr_seq_lock);
/* write lock is obtained... */
write_sequnlock(&mr_seq_lock);
The read path:
unsigned long seq;
do {
seq = read_seqbegin(&mr_seq_lock);
/* read data here ... */
} while (read_seqretry(&mr_seq_lock, seq));
seqlock的典型使用场景如下:
- 跟读操作的数量相比,写操作的数量很少。
- 在锁获取时,希望写操作优先。
使用seqlock的注意事项:
- 读操作耗时应比较短,否则容易导致过多次的读重试。
- 由于在读的过程中写操作可能正在修改数据,因此读操作可能会读取到某种不一致的状态。所以进行读取时,需要保护性的验证,以避免因读取不一致的错误数据导致错读。
3 Sequential Lock in Java
本想自己实现一个Java版本的Sequential lock,但是在Google了之后发现Makoto YUI已经提供了一比较好的实现,在其基础之上稍加改动之后的实现如下:
public final class SequentialLock {
//
private volatile int counter;
/**
*
*/
public int readBegin() {
return this.counter;
}
public boolean readRetry(int v) {
return (v & 1) == 1 || this.counter != v;
}
public synchronized void writeLock() {
//
if((this.counter & 1) != 0) {
throw new IllegalStateException("sequential lock is NOT reentrantable");
}
//
++this.counter;
}
public synchronized void writeUnlock() {
++this.counter;
}
}
首先,SequentialLock不是可重入的。其次由于读操作没有获得锁,因此读写之间需要额外的机制以保证内存可见性:对其volitle counter成员变量的读写保证了Sequential Lock保护的数据之间的happens bofore语义。
4 Reference
Linux Kernel Development 3rd Edition, Robert Love
分享到:
相关推荐
significance of a lock-in amplifier. As an introduction to the subject there follows a simple intuitive account biased towards light measurement applications. All lock-in amplifiers, whether ...
RedisLock.java
DistributedLock.java
Doorlock.java
LocalLock.java
integrated with an analog lock-in amplifier in 130-nm bulk CMOS. The integrated lock-in amplifier can support a modulation frequency of up to 10MHz with a gain of 54dB, a dynamic range of 42dB, and an...
Lock-in amplifiers were invented in the 1930’s [1, 2, 3] and commercialized [4] in the mid 20th century as electrical instruments capable of extracting signal amplitudes and phases in extremely ...
Lock锁是对象锁,仅在同一对象中,锁才会生效。(不做论证) (以下场景皆为单例模式下运行) lock.lock()的加锁方式,会使后续请求的线程堵塞等待。(方案A) lock.tryLock()的加锁方式,不会堵塞,会立即返回加锁...
It is oriented to get a better comprehension of the Lock-in amplifier, including its features and limitations. It has been defined to learn how to model a lock-in amplifier, a photo-detector, ...
本文总结了Java中Lock的各种用法。
Start Button Lock test applicatioin in c# Compact Framework
演示如何通过java nio设计lock
而lock是用java类,用java可以实现 2.synchronized可以锁住代码块,对象和类,但是线程从开始获取锁之后开发者不能进行控制和了解;lock则用起来非常灵活,提供了许多api可以让开发者去控制加锁和释放锁等等。
【Java面试题】lock与synchronized区别
Synchronous detectors can extract small signals, buried in the noise floor, to measure properties such as very small resistance, light absorption or reflection against bright backgrounds, or strain...
Performance of Phase Lock Loop in fading channel
Android手机的图片式锁屏和解锁程序的源码,源码的注释非常详细
锁定放大器是利用相关技术从噪声中提取微弱信号的常用方法之一。可以证明,当信号的频率和相位已知时,使用相关检测技术能使输出信号信噪比最大。数字锁定放大器比模拟锁定放大器具有稳定、精度高等优点,并且数字...
方波参考锁相放大器LabVIEW仿真程序