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锁框架综述

  • 相关阅读:
    es6异步编程 Promise 讲解 --------各个优点缺点总结
    js重新讲解继承,es5的一些继承,es6继承的改变 ----------由浅入深
    node.js里的buffer常见操作,copy,concat等实例讲解
    node.js 写流 createWriteStream----由浅入深
    node.js 读取文件--createReadStream
    Java的位运算符—— 与(&)、非(~)、或(|)、异或(^)
    XML的特殊字符处理
    mysql语句收藏
    MYSQL学习
    利用HTML5 LocalStorage实现跨页面通信channel
  • 原文地址:https://www.cnblogs.com/ch-forever/p/10219362.html
Copyright © 2011-2022 走看看