如何手寫JDK鎖
阿新 • • 發佈:2019-04-25
main toa http lean on() cep eth 結果 stack
手寫JDK鎖
需要三個步驟:
手寫一個類MyLock,實現Lock接口
重寫lock()方法
重寫unlock()方法
代碼:
public class MyLock implements Lock { //線程的原子操作類 AtomicReference<Thread> owner = new AtomicReference<>(); //如果有的線程搶不到,就放入等待隊列 public LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(); @Override public void lock() { //多個線程同時調用 while (!owner.compareAndSet(null, Thread.currentThread())) {//如果不成功 waiters.add(Thread.currentThread());//加入等待隊列 //Thread.currentThread().wait();//不能使用,wait()方法需要synchronized關鍵字 LockSupport.park();//讓當前線程等待 //取巧的方式:如果能執行到本行的話,說明這個線程被喚醒了,可以從等待隊列中刪除了 waiters.remove(Thread.currentThread()); } } @Override public void unlock() { //多個線程同時解鎖 if (owner.compareAndSet(Thread.currentThread(), null)) {//判斷當前線程是不是owner //釋放鎖 Object[] objects = waiters.toArray();//等待隊列轉化為數組 for (Object object : objects) {//喚醒等待隊列中所有的線程 Thread thread = (Thread) object; LockSupport.unpark(thread); } } } @Override public void lockInterruptibly() throws InterruptedException { // TODO Auto-generated method stub } @Override public boolean tryLock() { // TODO Auto-generated method stub return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { // TODO Auto-generated method stub return false; } @Override public Condition newCondition() { // TODO Auto-generated method stub return null; } }
測試
啟動10個線程,每個線程執行10000次incr()操作。
public class TestMyLock { int i = 0; int j = 0; Lock lock = new MyLock(); public void incr() { lock.lock(); try { i++; j++; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) throws InterruptedException { TestMyLock demo = new TestMyLock(); for (int k = 0; k < 10; k++) { new Thread(() -> { for (int i = 0; i < 10000; i++) { demo.incr(); } }).start(); } Thread.sleep(1000); System.out.println(demo.i); System.out.println(demo.j); } }
執行結果:
如何手寫JDK鎖