文章字数:658,阅读全文大约需要2分钟
自旋锁指的是线程在为获取到许可的情况下循环获取许可状态
实现
- TAS(Test And Set Lock)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class TASLock implements Lock { private AtomicBoolean mutex=new AtomicBoolean(false);
@Override public void lock() { while(mutex.getAndSet(true)){} } @Override public void unlock() { mutex.set(false); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class TASLockMain { private static TASLock cost=new TASLock ();
public static void func(){ cost.lock(); cost.unlock(); }
public static void main(String[] args) { for (int i = 0; i < 10000; i++) { Thread t=new Thread(()-> func()); t.start(); }
} }
|
不停的设置值会造成不停通知其他芯片值更改,产生缓存一致性风暴
- TTASLock(Test Test And Set Lock)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.test.lock; import java.util.concurrent.atomic.AtomicBoolean;
public class TTASLock implements Lock{ private AtomicBoolean mutex = new AtomicBoolean(false); @Override public void lock() { while(true){ while(mutex.get()){} if(!mutex.getAndSet(true)){ return; } } } @Override public void unlock() { mutex.set(false); } public String toString(){ return "TTASLock"; } }
|
先查看是否可用再设置,少了cas次数。但是在高征用的情况下会导致多次操作才能获取到锁,增加cas次数
- 回退算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| package com.test.lock; import java.util.Random;
public class Backoff { private final int minDelay, maxDelay; private int limit; final Random random; public Backoff(int min, int max){ this.minDelay = min; this.maxDelay = max; limit = minDelay; random = new Random(); } public void backoff() throws InterruptedException{ int delay = random.nextInt(limit); limit = Math.min(maxDelay, 2 * limit); Thread.sleep(delay); } } package com.test.lock; import java.util.concurrent.atomic.AtomicBoolean;
public class BackoffLock implements Lock{ private final int MIN_DELAY, MAX_DELAY; public BackoffLock(int min, int max){ MIN_DELAY = min; MAX_DELAY = max; } private AtomicBoolean mutex = new AtomicBoolean(false); @Override public void lock() { Backoff backoff = new Backoff(MIN_DELAY, MAX_DELAY); while(true){ while(mutex.get()){} if(!mutex.getAndSet(true)){ return; }else{ try { backoff.backoff(); } catch (InterruptedException e) { } } } } @Override public void unlock() { mutex.set(false); } public String toString(){ return "TTASLock"; } }
|
获取失败后线程休眠一段时间,减少冲突概率。缺点是休眠时间不好设置,需要根据硬件条件调整参数。