java 锁算法 h_几种锁算法的实现详解

Abstract

4种Lock的实现:

TASLock

TTASLock

CLHLock

MCSLock

TASLock

每一个Lock带有一个状态位,lock()与unlock()操作原子的改变状态位。false时可进入,true时spin。

public class TASLock implements Lock

{

AtomicBoolean state = new AtomicBoolean(false);

public void lock()

{

while(state.getAndSet(true))

{}

}

public void unlock()

{

state.set(false);

}

}

defect:

在锁被其他线程持有的情况下, while(state.getAndSet(true)) 会不停的将

state从true改为true

TTASLock

TASLock算法的改进。

public class TTASLock implements Lock()

{

AtomicBoolean state = new AtomicBoolean(false);

public void lock()

{

while (true)

{

while (state.get())

{};

if (! state.getAndSet(true))

return;

}

}

public void unlock()

{

state.set(false);

}

}

while (state.get()){} 是一个改进,效果是先看一眼lock的状态,当lock是false时,

再真正的执行 state.getAndSet(true) 。

当state.getAndSet(true) 的return为false时,说明之前的确是false,于是获得锁,return。

否则回到while(true),再次尝试获得锁。

defect:

在unlock时,state.set(false)还是会带来大量的cache miss。

cache miss VS cache hit

CLHLock

void initCLHlock()

{

q.locked = FALSE;

tail = &q;

}

void lock()

{

QNode* qnode = (QNode*)pthread_getspecific(myNode);

qnode->locked = TRUE;

QNode* pred = getAndSet(qnode);//原子的得到队尾,并将qnode设为新的队尾。

pthread_setspecific(myPred, pred);

while(pred->locked)

{

}

}

void unlock()

{

QNode* qnode = (QNode*)pthread_getspecific(myNode);

qnode->locked = FALSE;

QNode* pred = (QNode*)pthread_getspecific(myPred);

pthread_setspecific(myNode, pred);//unlock时必须将myNode指向前面的Node

}

NOTE :

unlock时必须将myNode指向前面的Node!

> 后果 :如果Thread A unlock()后,紧接着又进入

队尾, A的locked会再次被置为TRUE, Thread B还在看着Thread A 的locked字段,于是产生

deadlock。

初始时教室里面有一个空凳子, 每个学生来到门口排队时都自己带着一个凳子。

MCSLock

public class MCSLock implements Lock

{

AtomicReference tail;

ThreadLocal myNode;

public MCSLock()

{

queue = new AtomicReference(null);

myNode = new ThreadLocal()

{

protected QNode initialValue()

{

return new QNode();

}

};

}

...

class QNode

{

boolean locked = false;

QNode next = null;//与CLHLock相比,多了这个真正的next

}

}

public void lock()

{

QNode qnode = myNode.get();

QNode pred = tail.getAndSet(qnode);

if (pred != null)

{

qnode.locked = true;

pred.next = qnode;

//wait until predecessor gives up the lock

while(qnode.locked){}//将自己设为true然后spin,看似deadlock

}

}

public void unlock()

{

QNode qnode = myNode.get();

if (qnode.next == null) //后面没有等待线程的情况

{//------there is a gap!!!!

if (tail.compareAndSet(qnode, null))

return; //真的没有等待线程,则直接返回,不需要通知

//wait until predecessor fills in its next field

while (qnode.next == null){}

}

//右面有等待线程,则通知后面的线程

qnode.next.locked = false;

qnode.next = null;

}

NOTE:

unlock()要要特别的注意。

Summary

CLHLock的思想是当前线程在前一个线程的node上spin,每个线程unlock时修改自身的标记。

在共享总线结构下性能可以,无法应对分布式。

MCSLock 用于解决分布式并行的问题。每个线程都在自己的node上spin,当释放锁时通知

后面的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值