前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是锁?

什么是锁?

作者头像
王小明_HIT
发布2020-09-22 10:25:14
1K0
发布2020-09-22 10:25:14
举报
文章被收录于专栏:程序员奇点

什么是锁?

说到锁,门闩,密码锁,指纹锁,虹膜识别锁等,在计算机世界中,单机线程没有锁的概念,当有了资源竞争,才有锁的贵爱安出现。表示自己短暂的持有。

计算机锁从最开始的悲观锁,然后发展到后来的乐观锁,偏向锁,分段锁等。

锁有两种特性:互斥性和不可见性。

JUC 中的锁

并发包的类族,Lock 是 JUC 包的顶层接口。实现逻辑并未用到 synchronized ,而是利用 volatile 的可见性。

Lock 的继承类图,ReentrantLock 对于 Lock 接口的实现主要依赖了 Sync, 而 Sync 继承了 AbstractQueuedSynchronizer(AQS), AQS 是实现同步的基础工具。

在 AQS 中定义了,定义了一个 volatile int state 变量作为共享资源,如果线程获取资源失败,则进入 同步的 FIFO 队列;如果成功获取资源就执行临界区代码。

代码语言:javascript
复制
 protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

AQS 的子类可以定义不同性质的方法。

  • 比如可重入锁 ReentrantLock ,定义 State 为0 时,可以获取资源并设置1,如果已经获得资源,state 不断+1 ,释放资源 state-1 直到为0;
  • CountDown 初始化定义资源总量 state=count ,CountDown() 不断将 state-1 ,所以 CountDownLatch 是一次性的,用完之后只能重建一个,如果要循环使用,推进使用 CyclicBarrier 。
  • Semaphore 与 CountDownLatch 不同,定义了资源总量 state=permits. 当state >0 就可以获得锁,并将 state-1.当 state=0时只能等待其他线程释放锁。当释放锁时 state+1。当 Semaphore 的permits定义为1时,为互斥锁。permits>1 为共享锁。

CyclicBarrier 例子

每次 await 都会 count-1

代码语言:javascript
复制
int index = --count;

测试代码:

代码语言:javascript
复制
public class CyclicBarrierSample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {

            @Override
            public void run() {
                System.out.println("Action.... go again!");
            }
        });
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new CyclicWorker(barrier));
            t.start();
        }
    }
}

class CyclicWorker implements Runnable {

    private CyclicBarrier barrier;

    public CyclicWorker(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {

        try {
            for (int i = 0; i < 3; i++) {
                System.out.println("Executed!");
                barrier.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

    }
}

CountDownLatch 代码

代码语言:javascript
复制
public class LatchSample {

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(6);
        for(int i = 0; i < 5 ; i++){
            Thread t = new Thread(new FirstBatchWorker(latch));
            t.start();
        }
        for(int i = 0 ; i < 5;i++){
            Thread t = new Thread(new SecondBatchWorker(latch));
            t.start();
        }
        while(latch.getCount() != 1){
            Thread.sleep(100L);
        }
        System.out.println(" wait gor first batch finish");
        latch.countDown();
    }

}

class FirstBatchWorker implements Runnable {
    private CountDownLatch latch;

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

    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        System.out.println("First batch executed!");
        latch.countDown();
    }
}

class SecondBatchWorker implements Runnable {
    private CountDownLatch latch;

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

    @Override
    public void run() {
        try {
            latch.await();
            System.out.println("Second batch Executed!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员奇点 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是锁?
    • JUC 中的锁
      • CyclicBarrier 例子
        • CountDownLatch 代码
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档