深入探究 ReentrantLock 的应用和原理

news2024/11/23 12:20:31

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

在这里插入图片描述

文章目录

  • 1、ReentrantLock 简介
  • 2、ReentrantLock 的使用
    • 2.1、基本使用
    • 2.2、tryLock 的使用
    • 2.3、Condition 实现等待/通知机制
    • 2.4、多 Condition 使用
    • 2.5、公平锁
    • 2.6、可重入锁
  • 3、究根问底 - ReentrantLock 源码分析
  • 4、ReentrantLock 实际应用

1、ReentrantLock 简介

ReentrantLock 是 Java 中的一个锁实现,它提供了与 synchronized 关键字类似的功能,但是它更加灵活和可扩展。ReentrantLock 是一个可重入锁,也就是说同一个线程可以多次获得同一个锁而不会发生死锁。

ReentrantLock 的主要方法包括:

  1. lock():获取锁,如果锁已经被其他线程获取,则当前线程会被阻塞。
  2. unlock():释放锁。
  3. tryLock():尝试获取锁,如果锁已经被其他线程获取,则立即返回 false。
  4. tryLock(long timeout, TimeUnit unit):尝试获取锁,如果锁已经被其他线程获取,则当前线程会被阻塞,直到超时或者获取到锁。
  5. newCondition():创建一个 Condition 对象,用于实现等待/通知机制。

ReentrantLock 的优点之一是它提供了更细粒度的锁控制,可以通过 lockInterruptibly() 方法实现可中断的锁获取,也可以通过 tryLock() 方法实现非阻塞的锁获取。此外,ReentrantLock 还支持公平锁和非公平锁,可以通过构造函数来指定锁的类型。

需要注意的是,使用 ReentrantLock 时需要手动释放锁,否则可能会导致死锁。通常使用 try-finally 语句块来确保锁一定会被释放。

2、ReentrantLock 的使用

2.1、基本使用

首先看一段没有加锁的代码:

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  ReentrantLock 基本使用案例
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 20:47
 */
public class ReentrantLockDemo {

    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {          
                System.out.println("Thread 1 acquired the start.");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally { 
                System.out.println("Thread 1 released the end.");
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                System.out.println("Thread 2 acquired the start.");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println("Thread 2 released the end.");
            }
        });

        t1.start();
        t2.start();
    }
}

执行后的结果如下:

Thread 2 acquired the start.
Thread 1 acquired the start.
Thread 2 released the end.
Thread 1 released the end.

Process finished with exit code 0

两个线程同时开始,同时结束。接下来我们使用 ReentrantLock 加上锁,看看效果。

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  ReentrantLock 基本使用案例
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 20:47
 */
public class ReentrantLockDemo {

    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {
                lock.lock();
                System.out.println("Thread 1 acquired the start.");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("Thread 1 released the end.");
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                lock.lock();
                System.out.println("Thread 2 acquired the start.");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("Thread 2 released the end.");
            }
        });

        t1.start();
        t2.start();
    }
}

输出结果如下:

Thread 1 acquired the start.
Thread 1 released the end.
Thread 2 acquired the start.
Thread 2 released the end.

Process finished with exit code 0

我们创建了一个 ReentrantLock 对象,并在两个线程中使用它来控制共享资源的访问。在每个线程的 run 方法中,我们首先使用 lock() 方法获取锁,然后执行一些临界区代码,最后使用 unlock() 方法释放锁。由于 ReentrantLock 是可重入锁,因此同一个线程可以多次获取同一个锁,不会发生死锁。

2.2、tryLock 的使用

接下来我们看下 tryLock 的使用:

package com.pany.camp.reentrantLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  tryLock 的使用
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 20:55
 */
public class TryLockDemo {
    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {
                if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {
                    try {
                        System.out.println("Thread 1 acquired the lock.");
                        Thread.sleep(3000);
                    } finally {
                        lock.unlock();
                        System.out.println("Thread 1 released the lock.");
                    }
                } else {
                    System.out.println("Thread 1 failed to acquire the lock.");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {
                    try {
                        System.out.println("Thread 2 acquired the lock.");
                        Thread.sleep(1000);
                    } finally {
                        lock.unlock();
                        System.out.println("Thread 2 released the lock.");
                    }
                } else {
                    System.out.println("Thread 2 failed to acquire the lock.");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t2.start();
    }
}

我们首先创建了一个 ReentrantLock 对象,并在两个线程中使用它来控制共享资源的访问。然后,在每个线程的 run 方法中,我们使用 tryLock 方法尝试获取锁,等待 2000 毫秒。如果获取锁成功,就执行临界区代码,然后释放锁。如果获取锁失败,就输出一条失败信息。
输出结果如下:

Thread 1 acquired the lock.
Thread 2 failed to acquire the lock.
Thread 1 released the lock.

Process finished with exit code 0

这表明线程 1 成功获取了锁并执行了临界区代码,然后释放了锁。而线程 2 在等待 2000 毫秒后仍然无法获取锁,因此输出了一条失败信息。需要注意的是,在使用 tryLock 方法时,如果获取锁失败,线程并不会一直等待,而是会立即返回。这使得我们可以避免线程因为长时间等待锁而被阻塞的情况。

2.3、Condition 实现等待/通知机制

案例如下:

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  Condition 实现等待/通知机制
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 20:59
 */
public class ConditionDemo {
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition condition = lock.newCondition();
    private static boolean flag = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                while (!flag) {
                    System.out.println("Thread 1 is waiting.");
                    condition.await();
                }
                System.out.println("Thread 1 is notified.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                flag = true;
                System.out.println("Thread 2 is notifying.");
                condition.signal();
            } finally {
                lock.unlock();
            }
        });

        t1.start();
        t2.start();
    }
}

我们首先创建了一个 ReentrantLock 对象和一个 Condition 对象。然后,在线程 1 中,我们使用 while 循环来等待条件 flag 的满足,并在每次循环中使用 condition.await() 方法来释放锁并等待通知。在线程 2 中,我们设置条件 flag 为 true,并使用 condition.signal() 方法来通知线程 1,然后释放锁。

输出结果如下:

Thread 1 is waiting.
Thread 2 is notifying.
Thread 1 is notified.

Process finished with exit code 0

线程 1 在等待 flag 条件满足时被阻塞,并在线程 2 通知后被唤醒。需要注意的是,在使用 Condition 实现等待/通知机制时,必须在获取锁之后才能使用 await 和 signal 方法,否则会抛出 IllegalMonitorStateException 异常。

2.4、多 Condition 使用

代码如下:

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  多 Condition 使用
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 21:06
 */
public class MultiConditionDemo {
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition condition1 = lock.newCondition();
    private static final Condition condition2 = lock.newCondition();
    private static boolean flag = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                while (!flag) {
                    System.out.println("Thread 1 is waiting for condition 1.");
                    condition1.await();
                }
                System.out.println("Thread 1 is notified for condition 1.");
                condition2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        
        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                flag = true;
                System.out.println("Thread 2 is notifying for condition 1.");
                condition1.signal();
                while (!flag) {
                    System.out.println("Thread 2 is waiting for condition 2.");
                    condition2.await();
                }
                System.out.println("Thread 2 is notified for condition 2.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        
        t1.start();
        t2.start();
    }
}

我们创建了一个 ReentrantLock 对象和两个 Condition 对象。在线程 1 中,我们使用 while 循环来等待条件 flag 的满足,并在每次循环中使用 condition1.await() 方法来释放锁并等待通知。在线程 2 中,我们设置条件 flag 为 true,并使用 condition1.signal() 方法来通知线程 1,然后等待条件 flag2 的满足,使用 condition2.await() 方法来释放锁并等待通知。在线程 1 中,我们使用 condition2.signal() 方法来通知线程 2。

输出如下:

Thread 1 is waiting for condition 1.
Thread 2 is notifying for condition 1.
Thread 2 is notified for condition 2.
Thread 1 is notified for condition 1.

Process finished with exit code 0

线程 1 在等待条件 flag1 满足时被阻塞,并在线程 2 通知后被唤醒。然后线程 1 通知线程 2 等待的条件 flag2,线程 2 在等待条件 flag2 满足时被阻塞,并在线程 1 通知后被唤醒。需要注意的是,在使用多个 Condition 实现等待/通知机制时,每个 Condition 都应该有对应的等待和通知逻辑,并且必须在获取锁之后才能使用 await 和 signal 方法,否则会抛出 IllegalMonitorStateException 异常。

2.5、公平锁

公平锁是一种锁的实现方式,它可以保证多个线程按照它们请求锁的顺序获取锁。也就是说,如果一个线程请求锁,但是锁已经被其他线程占用了,那么这个线程将被放置在一个等待队列中,直到它的请求被处理并且锁被释放。然后,等待队列中的下一个线程才能获取锁。这种方式可以保证线程获取锁的公平性,避免线程饥饿现象的发生。但是,公平锁的实现可能会导致性能下降,因为它需要维护等待队列并进行线程切换。因此,在实现锁时需要根据具体情况来选择公平锁或非公平锁。

以下就是公平锁的使用:

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  公平锁
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 21:09
 */
public class FairLockDemo {
    private static final ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 1 acquired the lock.");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 2 acquired the lock.");
            } finally {
                lock.unlock();
            }
        });
        
        t1.start();
        t2.start();
    }
}

2.6、可重入锁

可重入锁是一种线程同步机制,也称为递归锁。它允许线程多次获取同一个锁,而不会出现死锁的情况。当一个线程获取了锁后,它可以再次获取锁,而不会被阻塞。当线程释放锁时,它必须释放相同次数的锁,否则其他线程将无法获取锁。可重入锁通常用于解决递归函数或多个方法之间的互斥访问问题。Java 中的 ReentrantLock 就是一种可重入锁的实现。

以下是可重入锁的代码:

package com.pany.camp.reentrantLock;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @description:  可重入锁
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-25 21:11
 */
public class ReentrantLockDemo1 {
    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 1 acquired the lock.");
                Thread.sleep(1000);
                lock.lock();
                try {
                    System.out.println("Thread 1 acquired the lock again.");
                } finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 2 acquired the lock.");
            } finally {
                lock.unlock();
            }
        });
        t1.start();
        t2.start();
    }
}

3、究根问底 - ReentrantLock 源码分析

  1. 构造函数

ReentrantLock 的构造函数有两个重载版本,分别是无参构造函数和带公平性参数的构造函数。其中,公平性参数用于指定是否使用公平锁,默认为非公平锁。

public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
  1. 加锁与解锁

ReentrantLock 的加锁和解锁操作都是通过内部类 Sync 来实现的。Sync 是一个抽象类,它有两个子类 NonfairSync 和 FairSync,分别对应非公平锁和公平锁。

abstract static class Sync extends AbstractQueuedSynchronizer {
    // 加锁
    abstract void lock();
     // 解锁
    protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }
}

static final class NonfairSync extends Sync {
    // 加锁
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
     // 尝试加锁
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}

static final class FairSync extends Sync {
    // 加锁
    final void lock() {
        acquire(1);
    }
     // 尝试加锁
    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;
    }
}

在 NonfairSync 中,加锁操作首先尝试使用 compareAndSetState 方法将 state 从 0 修改为 1,如果成功则表示获取锁成功,否则就调用 acquire 方法进入等待队列。在 FairSync 中,加锁操作直接调用 acquire 方法进入等待队列,如果前面有等待的线程,则当前线程会进入等待队列,直到前面所有线程都执行完毕后才会获取锁。

在解锁操作中,会判断当前线程是否为持有锁的线程,如果不是则抛出 IllegalMonitorStateException 异常,否则就将 state 减去 releases,并判断是否需要释放锁。如果 state 减去 releases 后等于 0,则表示当前线程已经释放了锁,需要将 exclusiveOwnerThread 置为 null。

  1. 其他方法

除了加锁和解锁操作之外,ReentrantLock 还提供了一些其他方法,如 tryLock、tryLock(long time, TimeUnit unit)、lockInterruptibly、newCondition 等。

其中,tryLock 方法用于尝试获取锁,如果成功则返回 true,否则返回 false。tryLock(long time, TimeUnit unit) 方法用于在指定的时间内尝试获取锁,如果成功则返回 true,否则返回 false。lockInterruptibly 方法用于可中断地获取锁,如果当前线程被中断则会抛出 InterruptedException 异常。newCondition 方法用于创建一个 Condition 对象,用于实现线程间的协作。

4、ReentrantLock 实际应用

ReentrantLock是Java中的一个锁实现类,它可以用于多线程并发控制,常用于以下场景:

  1. 临界区控制
    当多个线程需要同时访问共享资源时,需要使用锁来保证线程安全。ReentrantLock可以用于控制临界区的访问,避免多个线程同时访问共享资源导致的数据竞争和线程安全问题。

  2. 死锁避免
    ReentrantLock支持可重入性,即同一个线程可以多次获取该锁。这种特性可以避免死锁的发生,因为如果一个线程已经持有了该锁,再次获取该锁时不会被阻塞,而是直接返回。

  3. 公平锁控制
    ReentrantLock提供了公平锁和非公平锁两种模式。公平锁可以保证多个线程按照先后顺序获取锁,避免线程饥饿问题。非公平锁则不保证线程获取锁的顺序,可能会导致某些线程一直无法获取到锁。

  4. 条件变量控制

ReentrantLock还提供了Condition接口,可以用于实现线程间的协作。通过Condition接口的await()和signal()方法,可以实现线程的等待和唤醒操作,从而更加灵活地控制线程的执行顺序。

总之,ReentrantLock是一个非常实用的多线程并发控制工具,可以用于各种场景下的线程同步和互斥操作。

在这里插入图片描述

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/684379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信开发者工具-导入小程序项目会自动切换到小游戏打开出错的解决方案

微信开发者工具导入小程序项目会自动切换到小游戏打开出错&#xff0c; 提示Error 提示appid错误&#xff0c;如下图 错误 Error: INVALID_TOKEN...表示网络已断开&#xff0c; 检查开发工具是否连接到网络&#xff0c; 或注销重新登录开发工具试试 提示缺少文件 如果提示缺…

智能安全用电技术电气火灾监控的应用介绍 安科瑞 许敏

摘要&#xff1a;智能安全用电技术在智慧监狱的应用&#xff0c;可以提升监狱智能化管控水平和降低能耗。文章以智能安全用电技术为入手点&#xff0c;简要分析了监狱用电现状&#xff0c;论述了智能安全用电技术在智慧监狱中的具体应用&#xff0c;对智能安全用电技术在智慧监…

【面试题12】HTTP协议三次握手和四次挥手分别是什么

文章目录 一、概览二、三次握手2.1 第一步&#xff1a;客户端向服务端发送 SYN&#xff08;同步&#xff09;包2.2 第二步&#xff1a;服务端返回 ACK&#xff08;确认&#xff09;包和 SYN 包2.3 第三步&#xff1a;客户端返回 ACK&#xff08;确认&#xff09;包 三、四次挥手…

今日分享:音频格式转换软件

小林最近特别喜欢唱歌&#xff0c;不过总是遇到一些麻烦&#xff0c;例如自己录制的音频格式无法在其他设备上播放&#xff0c;或者想把某个歌曲转成适合自己播放的格式。这时候就需要一个好用的音频格式转换器啦&#xff01;小林找了一圈&#xff0c;终于找到了几款可爱又好用…

大数据应用——工程实践III

任务一&#xff1a;完成Hadoop集群部署前环境的准备工作 1.1 虚拟机环境准备 1. 安装虚拟机 2. 克隆虚拟机 3. 修改网络配置 4. 修改主机名和映射 5. 关闭防火墙 1.2 安装JDK 1.3 安装Hadoop 1.4 集群配置 1. 编写集群分发脚本xsync 2. 集群部署规划 表 1.1 hadoop101 …

一份老网工珍藏多年的网络配置笔记

我的网工朋友大家好 俗话说得好&#xff0c;好记性不如烂笔头。 学生时代&#xff0c;我们考试前最喜欢看的就是学霸笔记&#xff0c;但工作之后&#xff0c;却没有人会愿意借给你他们的珍藏笔记了。 今天&#xff0c;想给你分享一个老网工分享在网上的精选笔记&#xff0c;…

java 8 新特性讲解Optional类--Fork/Join 框架--新时间日期API--以及接口的新特性和注解

Optional类 到目前为止&#xff0c;臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前&#xff0c;为了解决空指针异常&#xff0c;Google公司著名的Guava项目引入了Optional类&#xff0c;Guava通过使用检查空值的方式来防止代码污染&#xff0c;它鼓励程序员写…

六、Docker容器数据卷

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、容器数据卷1.1 容器数据卷1.2 怎么用1.3 能干什么 二、实践案例2.1 启动ubuntu容器实例&#xff0c;挂载目录&#xff1a;2.2 在ubuntu容器实例的/tmp/docker_data中…

Android 组件化架构思路

作者&#xff1a;往事一块六毛八 为什么要模块化/组件化 随着APP版本不断的迭代&#xff0c;新功能的不断增加&#xff0c;业务也会变的越来越复杂&#xff0c;APP业务模块的数量有可能还会继续增加&#xff0c;而且每个模块的代码也变的越来越多&#xff0c;这样发展下去单一…

GNS3报错“unable to open TAP device tap0 (No such file or directory)”解决

系统&#xff1a;MacOS 13.4 GNS3版本&#xff1a;2.2.35.1 Tunnelblick&#xff1a;3.8.8b 起因 在gns3中使用cloud节点创建 tap 接口连接路由器报错&#xff1a; 解决办法 借助 Tunnelblick工具创建 Tap 虚拟网卡。Tunnelblick下载地址&#xff1a; https://tunnelblic…

Kubernetes入门实战课-初始容器

Kubernetes入门实战课-初始容器 文章目录 Kubernetes入门实战课-初始容器课前准备初始容器Docker 的形态Docker 的安装Docker 的架构 容器的本质隔离原因与虚拟机区别隔离是怎么实现的 镜像创建容器镜像&#xff1a;如何编写正确、高效的Dockerfile镜像的内部机制是什么Dockerf…

MySQL数据库连接查询和存储过程

MySQL数据库连接查询和存储过程 一、连接查询1、内连查询2、左连接3、右链接 二、存储过程1、存储过程简介2、存储过程的优点3、语法3.1 参数分类3.2 不加参数的存储过程3.3 带参数的存储过程3.4删除存储过程3.5 事务和存储过程有什么区别&#xff1f; 三、总结1、连接查询2、存…

【Java项目中 利用Redis实现数据缓存】

文章目录 Java SpringBoot项目中 用Redis实现数据缓存1 环境搭建1.1 maven坐标1.2 配置文件1.3 配置类 2 实现缓存短信验证码3 缓存菜品数据4 Spring Cache 缓存框架4.1 Spring Cache介绍4.2 Spring Cache常用注解4.3 Spring Cache使用方式 Java SpringBoot项目中 用Redis实现数…

一文了解Moonbeam互连合约

什么是互连合约Connected Contracts 简单来说&#xff0c;互连合约是通过Moonbeam连接其他区块链上的一个或多个智能合约&#xff0c;其允许目标链上的用户通过跨链消息传递协议在一个应用中操作不同链上的资产或是服务。 通过互连合约方案&#xff0c;不同迥异的公链技术架构…

计算机内部总线详解

文章目录 总线概述地址总线位宽 数据总线位宽CPU性能指标 例题 总线概述 众所周知&#xff0c;总线就是用来帮助连接两个或多个计算机组件&#xff0c;用于数据传输&#xff0c;计算机内部存在三种类型的总线&#xff1a; 地址总线&#xff1a;用于传输指示计算机中的内存或外…

【uboot1】常用指令

文章目录 1.U-Boot命令之常用命令&#xff1a;7.U-Boot命令之EMMC和SD卡操作命令&#xff1a;一般EMMC和SD卡是同一个东西&#xff0c;没特殊说明&#xff0c;统一MMC来代指EMMC和SD卡8.U-Boot命令之内存操作命令&#xff1a;直接对DRAM进行读写操作&#xff0c;uboot命令中的数…

MySQL数据库高级查询语句

MySQL数据库高级查询语句 一、语句SELECT ----显示表格中一个或数个字段的所有数据记录DISTINCT ----不显示重复的数据记录WHERE ----有条件查询AND OR ----且 或IN ----显示已知的值的数据记录BETWEEN ----显示两个值范围内的数据记录通配符 ----通常通配符都是跟 LIKE 一起使…

强化学习从基础到进阶-案例与实践[5]:梯度策略、添加基线(baseline)、优势函数、动作分配合适的分数(credit)

【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧&#xff08;调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍&#xff1a;【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧…

解决关于msvcp120.dll丢失的问题(解决方法)

msvcp120.dll是微软软件包的一部分。它是一个库文件&#xff0c;可用于支持软件运行时&#xff0c;msvcp120.dll的作用是提供计算机程序所需的标准库&#xff0c;msvcp120.dll还负责管理堆内存、线程和异常处理函数等。在使用windows编写的应用程序中&#xff0c;通常需要使用此…

【新星计划·2023】Linux系统的架构和组件讲解

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 前言 本文将讲解Linux系统的架构和组件。 目录 一、Linux系统的架构 1、硬件层 2、内核层 3、进程管理子系统 4、内存管理子系统 5、…