
package code.ss.demo1.jvm; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; public class BiasLock { public static final int SPIN_THRESHOLD_TIMES = 300; static long a = 0; static class LockThread extends Thread{ AtomicReference<LockObject> lock = new AtomicReference<>(); public LockThread(Runnable target) { super(target); } } public static void main(String[] args) throws InterruptedException { LockObject lockObject = new LockObject(); ArrayList<String> strings = new ArrayList<>(); int size = 30; Thread[] threads = new Thread[size]; for (int i = 0; i < size; i++) { threads[i] = new LockThread(() -> { int b = 0; while (b <= 10) { lock(lockObject); a++; strings.add(String.valueOf(a)); unlock(lockObject); b++; } }); } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } System.out.println("size:" + strings.size()); System.out.println(a); assert a == (size * 10); } static class LockObject { //0 is not biased,1 is biased AtomicInteger lockStatus = new AtomicInteger(0); AtomicInteger baisedThreadId = new AtomicInteger(-1); ReentrantLock reentrantLock = new ReentrantLock(); AtomicReference<Thread> smallLockReference = new AtomicReference(); AtomicInteger spainThreadCount = new AtomicInteger(0); AtomicInteger spinCount = new AtomicInteger(0); } public static final int BlOCK = 5; public static final int SPIN_LOCK = 2; public static final int NO_LOCK = 0; public static final int LOCK_BAISED = 1; static public void unlock(LockObject lock) { int status = lock.lockStatus.get(); if (status == NO_LOCK) { return; } if (status == LOCK_BAISED) { //解除偏向 int i = lock.baisedThreadId.get(); if (lock.baisedThreadId.compareAndSet(i, -1)) { lock.lockStatus.compareAndSet(LOCK_BAISED, NO_LOCK); } } if (status == SPIN_LOCK) { Thread thread = Thread.currentThread(); lock.smallLockReference.compareAndSet(thread, null); } if (status == BlOCK) { if (lock.smallLockReference.get() == Thread.currentThread()) { //spin lock lock.smallLockReference.set(null); }else{ lock.reentrantLock.unlock(); } } } static public void lock(LockObject lock) { int status = lock.lockStatus.get(); System.out.println("status:" + status); if (status == BlOCK) { lock.reentrantLock.lock(); } else if (status == SPIN_LOCK) { raiseSpinLock(lock); // if (lock.smallLockReference.get() != null) { // if (lock.smallLockReference.get() == Thread.currentThread()) { // return; // } // }else{ // lock.lockStatus.compareAndSet(SPIN_LOCK, BlOCK); // lock.reentrantLock.lock(); // } } else if (status == NO_LOCK) { if (lock.baisedThreadId.get() == -1) { boolean b = lock.baisedThreadId.compareAndSet(0, Thread.currentThread().hashCode()); if (b) { if (lock.lockStatus.compareAndSet(NO_LOCK, LOCK_BAISED)) { return; } } } raiseSpinLock(lock); } else if (status == LOCK_BAISED) { //已偏向 if (lock.baisedThreadId.get() == Thread.currentThread().hashCode()) { return; } lock.lockStatus.set(SPIN_LOCK); //升级到轻量级锁 raiseSpinLock(lock); } } private static void notify_lock(LockObject lock) { // LockSupport.unpark(); } private static void block_lock(LockObject lock) { // LockSupport.park(); } private static void raiseSpinLock(LockObject lock) { while (true) { int status = lock.lockStatus.get(); if (status == BlOCK) { lock.reentrantLock.lock(); return; } if (status <= SPIN_LOCK) { if (lock.lockStatus.compareAndSet(status, SPIN_LOCK)) { break; } } } LockThread c = (LockThread) Thread.currentThread(); c.lock.compareAndSet(null, lock); int spinCount = 0; while (true) { if (spinCount >= SPIN_THRESHOLD_TIMES) { lock.lockStatus.set(BlOCK); lock.reentrantLock.lock(); break; } int i = lock.spainThreadCount.incrementAndGet(); if (i > 3) { System.out.println("// stop spin cause too many thread contend,go to block lock"); lock.lockStatus.set(BlOCK); lock.reentrantLock.lock(); break; } if (lock.smallLockReference.compareAndSet(null, c)) { //get lock success lock.spainThreadCount.decrementAndGet(); System.out.println("//spin :" + spiCount); break; } else { Thread.yield(); spinCount++; } lock.spinCount.incrementAndGet(); } } } 交流下,理解有问题吗?
1 AoEiuV020 2021-10-21 17:19:30 +08:00 用代码交流理论上是可以的,但应该没多少人会看见一段代码就花时间理解其中思想, 我是说建议楼主同时用中文简述一下自己的想法, |
2 wooyulin 2021-10-21 18:28:32 +08:00 同楼上,思路先说说吧,不然不知道值不值得看 |
3 cubecube 2021-10-21 19:20:43 +08:00 偏向锁在 jdk17 都被删除了。没有看的必要了。 |
4 BQsummer 2021-10-21 19:46:50 +08:00 我看了这帖子才知道偏向锁要被删除了,查了下,原因是偏向锁提高不了多少性能,代码复杂度提高了。 https://openjdk.java.net/jeps/374 |
5 JLX 2021-10-21 20:04:40 +08:00 LZ 能讲一下设计思想吗,不然不太好理解(我比较菜鸡) |