烂笔头

不积跬步无以至千里

0%

java 自旋锁

基本实现

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
/**
* 自旋实现锁
*/
public class MyLock implements ILock {
private volatile int status = 0;

public void lock() {
while (!compareAndSwap(1)) {
System.out.println(Thread.currentThread().getName() + "waiting");
//v1 自旋+yeild 让出CPU,还是有很大几率被CPU重新调度,CPU消耗大
//Thread.yield();
//sleep + 自旋 让出CPU,但是sleep时长难以确定
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
System.out.println(Thread.currentThread().getName() + "lock,");
}

private boolean compareAndSwap(int newValue) {
if (0 == status) {
status = newValue;
return true;
}
return false;
}

public void unlock() {
status = 0;
System.out.println(Thread.currentThread().getName() + "unlock");
}
}

park实现

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
/**
* park+自旋
*/
public class ParkLock implements ILock {
private volatile int status = 0;
private Queue<Thread> queue = new ConcurrentLinkedQueue<>();

public void lock() {
while (!compareAndSwap(1)) {
System.out.println(Thread.currentThread().getName() + "waiting");
threadPark();
}
System.out.println(Thread.currentThread().getName() + "lock,");
}

private void threadPark() {
queue.add(Thread.currentThread());
status = 1;
LockSupport.park();
}

private boolean compareAndSwap(int newValue) {
if (0 == status) {
status = newValue;
return true;
}
return false;
}

public void unlock() {
status = 0;
Thread poll = queue.poll();
LockSupport.unpark(poll);
System.out.println(Thread.currentThread().getName() + "unlock");
}
}

测试代码

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
public class CountRun implements Runnable {
private static ParkLock lock = new ParkLock();
private final CountDownLatch latch;

public CountRun(CountDownLatch latch) {
this.latch = latch;
}

@Override
public void run() {
lock.lock();
for (int i = 0; i < 100; i++) {
CountMain.INIT_VALUE++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.unlock();
latch.countDown();
}
}

public class CountMain {
public static int INIT_VALUE = 0;
public static final int LIMIT = 3;

public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(LIMIT);
new Thread(new CountRun(countDownLatch)).start();
new Thread(new CountRun(countDownLatch)).start();
new Thread(new CountRun(countDownLatch)).start();
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + ":" + CountMain.INIT_VALUE);
}
}