zoukankan      html  css  js  c++  java
  • JUC同步锁(五)

    根据锁的添加到Java中的时间,Java中的锁,可以分为“同步锁”“JUC包中的锁”

    一、同步锁--synchronized关键字

    通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。

    同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!

    二、JUC包中的锁

    相比同步锁,JUC包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。Lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区,相对于synchronized,Lock接口及其实现类提供了更加强大、灵活的锁机制。

    JUC包中的锁,包括:

    • Lock接口
    • ReadWriteLock接口
    • Condition接口
    • ReentrantLock独占锁
    • ReentrantReadWriteLock读写锁
    • CountDownLatch
    • CyclicBarrier
    • Semaphore
    • AbstractOwnableSynchronizer抽象类
    • AbstractQueuedSynchronizer抽象类
    • AbstractQueuedLongSynchronizer抽象类

    下面以简单的实例对两种锁进行介绍:

    (1)简单的锁synchronized:

    public class ThreadTest {
        public void test(){
            synchronized(this){
                //do something
            }
        }
    }
    

    (2)lock锁实现

    public class ThreadTest {
        Lock lock = new Lock();
        public void test(){
            // 当前线程会被阻塞,直到该Lock对象的unlock()方法被调用
            lock.lock();
            //do something
            // 释放锁
            lock.unlock();
        }
    }
    

    lock()方法会对Lock实例对象进行加锁,因此所有对该对象调用lock()方法的线程都会被阻塞,直到该Lock对象的unlock()方法被调用。

    Lock锁实现:

    public final synchronized void lock() throws InterruptedException{
        // 当isLocked为true时,调用lock()的线程在wait()调用上阻塞等待。
        while(this.locked) {
            this.wait();
        }
    	// 让其它正在调用lock()方法的线程能够在Lock实例上加锁。
        this.locked = true;
    }
    
    public final synchronized void unlock() {
        this.locked = false;
        this.notifyAll();
    }
    

    ​ 当isLocked为true时,调用lock()的线程在wait()调用上阻塞等待。为防止该线程没有收到notify()调用也从wait()中返回,这个线程会重新去检查isLocked条件以决定当前是否可以安全地继续执行还是需要重新保持等待,而不是认为线程被唤醒了就可以安全地继续执行了。如果isLocked为false,当前线程会退出while(isLocked)循环,并将isLocked设回true,让其它正在调用lock()方法的线程能够在Lock实例上加锁。

    三、详解JUC包中的各个锁

    锁的框架图如下:

    img

    (1)Lock 接口

    Lock为接口类型,Lock实现提供了比使synchronized方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的Condition对象。

    JUC 包中的 Lock 接口支持那些语义不同 (重入、公平等) 的锁规则。所谓语义不同,是指锁可是有 “公平机制的锁”、”非公平机制的锁”、”可重入的锁” 等等。”公平机制” 是指 “不同线程获取锁的机制是公平的”,而 “非公平机制” 则是指 “不同线程获取锁的机制是非公平的”,”可重入的锁” 是指同一个锁能够被一个线程多次获取。

    (2)ReadWriteLock

    ​ ReadWriteLock为接口类型, 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。

    ​ ReadWriteLock 接口以和 Lock 类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC 包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。

    (3)Condition

    ​ Condition为接口类型,它将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。可以通过await(),signal()来休眠/唤醒线程。

    ​ Condition 需要和 Lock 联合使用,它的作用是代替 Object 监视器方法,可以通过 await(),signal() 来休眠 / 唤醒线程。Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。

    (4)LockSupport

    ​ LockSupport 提供 “创建锁” 和“其他同步类的基本线程阻塞原语”。
      LockSupport 的功能和 “Thread 中的 Thread.suspend()和 Thread.resume()有点类似”,LockSupport 中的 park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。但是 park()和 unpark()不会遇到 “Thread.suspend 和 Thread.resume 所可能引发的死锁” 问题。

    (5)CountDownLatch

    ​ CountDownLatch为常用类,它是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

    (6)ReentrantLock

    Reentrant:可重入

    ​ ReentrantLock 是独占锁。所谓独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。ReentrantLock 锁包括 “公平的 ReentrantLock” 和 “非公平的 ReentrantLock”。”公平的 ReentrantLock” 是指 “不同线程获取锁的机制是公平的”,而 “非公平的  ReentrantLock” 则是指 “不同线程获取锁的机制是非公平的”,ReentrantLock 是 “可重入的锁”。

    参考链接

    本片文章,主要整理自互联网,便于自己复习知识所用,以下为参考链接!

    【1】Java并发编程实战-----“J.U.C”:锁,lock

    【2】JUC包中的锁

    【3】java多线程系列三:JUC锁

    【4】JUC锁框架综述

  • 相关阅读:
    pipelinewise 学习二 创建一个简单的pipeline
    pipelinewise 学习一 docker方式安装
    Supercharging your ETL with Airflow and Singer
    ubuntu中使用 alien安装rpm包
    PipelineWise illustrates the power of Singer
    pipelinewise 基于singer 指南的的数据pipeline 工具
    关于singer elt 的几篇很不错的文章
    npkill 一个方便的npm 包清理工具
    kuma docker-compose 环境试用
    kuma 学习四 策略
  • 原文地址:https://www.cnblogs.com/ch-forever/p/10219362.html
Copyright © 2011-2022 走看看