锁的作用就是当一个线程持有锁的时候,其他线程都不能对锁定的共享变量进行操作,简而言之把并行操作变为串行操作。

用java如何实现,我们定义一个持有锁的标志,当一个线程持有锁的时候,把其他线程挂起,当这个持有锁的线程释放锁时,把其中一个的挂起的线程唤醒。

实现主要用到Unsafe的park方法挂起线程和unpark方法唤醒线程,java是不允许直接操作内存,所以这个类不能被直接引用,可以通过反射来获取权限。

锁之简单实现;

public class SimpleLock implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -8815596805585415733L;

    private volatile int state;

    private static final Unsafe unsafe;

    private static final long stateOffset;

    private volatile Thread ownerThread;

    private static final BlockingQueue<Thread> blockQueue;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null);
            stateOffset = unsafe.objectFieldOffset(SimpleLock.class.getDeclaredField("state"));
            blockQueue = new LinkedBlockingQueue<>();
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    private boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    private void setState(int state) {
        this.state = state;
    }

    private int getState() {
        return this.state;
    }

    public void lock() {
        /**
         * 当前线程获得锁,当前线程就运行,如果没有获得锁,当前线程就中断。
         */
        Thread current = Thread.currentThread();
        if (compareAndSet(0, 1)) {
            ownerThread = current;
        } else {
            // 如果当前线程持有锁,且的它未完成任务,其他线程挂起,否则等待线程里面的其中一个线程获得锁
            if (ownerThread == current) {
                // System.out.println(ownerThread.getState().toString());
                if (ownerThread.getState() == Thread.State.TERMINATED) {
                    setState(0);
                    LockSupport.unpark(ownerThread);
                }
            } else {
                blockQueue.add(current);
                LockSupport.park(this);
            }
        }
    }

    public void unlock() {
        LockSupport.unpark(blockQueue.poll());
        setState(0);
    }

    public static void main(String[] args) {
        class RunThread implements Runnable {
            private SimpleLock simpleLock = new SimpleLock();
            int i = 0;

            @Override
            public void run() {
                simpleLock.lock();
                for (int j = 0; j < 10; j++) {
                    i++;
                    System.out.println(String.format("ThreadName:%s,i:%d", Thread.currentThread().getName(), i));
                }
                simpleLock.unlock();

            }
        }
        RunThread runThread = new RunThread();
        Thread t1 = new Thread(runThread);
        t1.start();
        Thread t2 = new Thread(runThread);
        t2.start();
        Thread t3 = new Thread(runThread);
        t3.start();
    }
}

 

posted on 2018-12-19 14:25  柳无情  阅读(97)  评论(0编辑  收藏  举报