C++异步编程

thread

std::thread 类代表一个单独的执行线程。在创建与线程对象相关联时,线程会立即开始执行(在等待操作系统调度的延迟之后),从构造函数参数中提供的顶层函数开始执行。顶层函数的返回值被忽略,如果它通过抛出异常终止,则会调用 std::terminate

std::thread 对象也可以处于不表示任何线程的状态(默认构造、移动、分离或加入之后),而且执行线程可能不与任何 std::thread 对象关联(分离之后)。

std::thread 不可复制构造或复制赋值,但是可以移动构造和移动赋值。

构造函数:

  1. 默认构造函数。创建一个不表示任何线程的新的std::thread对象。
  2. 移动构造函数。将 other 所表示的线程转移给新的 std::thread 对象。在此调用后,other 不再表示一个线程。
  3. 创建一个新的 std::thread 对象并将其与一个线程关联起来,且新的线程开始执行。

析构函数:

销毁线程对象。 如果 *this 有关联的线程 (joinable() == true),则调用 std::terminate()。

移动构造函数:

如果 *this 仍然关联着一个正在运行的线程(即 joinable() == true),则调用 std::terminate() 终止程序。否则,将 other 的状态赋值给 *this,并将 other 设为默认构造状态。

Observers:

joinable:

joinable() 函数用于检查 std::thread 对象是否标识着一个活动的执行线程。一个默认构造的线程是不可结合(joinable)的。

get_id:

返回 std::thread::id 的值。

native_handle:

返回实现定义的底层线程句柄。对于LInux系统来说,就是返回一个Linux系统中定义的线程类型值。

hardware_concurrency(static):

返回实现支持的并发线程数。该值应仅被视为提示。

Operations:

join:

阻塞当前线程,直到由 *this 标识的线程执行完成。

detach:

将执行线程与线程对象分开,允许独立继续执行。调用 detach *this 后不再拥有任何线程。

swap:

交换两个线程对象的底层句柄

Non-member functions:

std::swap:

重载了次类的std::swap算法,其实现相当于调用成员函数swap。

管理线程的非成员函数:

std::this_thread::yield();

重新调度线程的执行,让其他线程运行。

std::this_thread:get_id();

返回当前线程的id。

std::this_thread::sleep_for();

阻塞当前线程的执行,至少持续指定的 sleep_duration。

由于调度或资源争用延迟的原因,此函数可能会阻塞的时间超过 sleep_duration。

std::sleep_until();

阻塞当前线程的执行,直到达到指定的 sleep_time。

std::mutex

互斥锁, 一种独占性资源,因此没有复制构造函数和复制运算符。线程通过调用它的成员函数lock或try_lock才能拥有该互斥量。如果一个互斥量在任何线程仍然拥有它的情况下被销毁,或者一个线程在拥有互斥量时终止,程序的行为是未定义的。

Member types:

构造函数:

只有默认构造函数。复制构造函数被删除。也没有移动构造函数。

Locking

lock:

对互斥量加锁。

try_lock:

尝试锁定互斥锁。立即返回,成功锁定后返回true,否则返回false。

unlock:

对互斥锁解决。

Native handle:

native_handle();

返回底层实现定义的本地句柄对象。

std::timed_mutex

timed_mutex 提供了mutex的全部功能,除此之外,还提供了超时的情况下锁的是否锁定的问题。在Linux系统中,它和std::mutex的native_handle()的返回值是一样的。

它提供了std::mutex的全部的成员函数。以下是std::mutex没有的两个成员函数。

Locking:

try_lock_for:

尝试锁定互斥。阻塞直到指定的持续时间 timeout_duration 已过(超时)或锁被获取(拥有互斥),以先到者为准。成功获取锁后返回 true,否则返回 false。

try_lock_until:

尝试锁定互斥量。阻塞直到达到指定的超时时间(timeout_time)或成功获取锁定(拥有互斥量),以先到者为准。成功获取锁定时返回 true,否则返回 false。

如果超时时间已经过去,此函数的行为类似于 try_lock()。

std::shared_mutex

shared_mutex 具有两个级别的访问权限:

  • 共享访问:多个线程可以共享对同一个互斥量的拥有权。
  • 独占访问:只有一个线程可以拥有互斥量。

在同一个线程内,同一时间只能获取一个锁(共享锁或独占锁)。它不能被拷贝。

构造函数:

默认构造函数;没有拷贝构造函数和移动构造函数。

没有赋值运算符。

Exclusive locking

lock:

获得对 shared_mutex 的独占所有权。如果另一个线程在同一个 shared_mutex 上持有独占锁或共享锁,调用锁定将阻塞执行,直到所有此类锁都被释放。当 shared_mutex 以独占模式锁定时,不能同时持有其他任何类型的锁。

try_lock:

尝试锁定互斥。立即返回。成功锁定后返回 true,否则返回 false。即使当前互斥项未被任何其他线程锁定,该函数也允许假失败并返回 false。如果 try_lock 被一个已经在任何模式(共享或独占)下拥有该互斥项的线程调用,其行为将是未定义的。

unlock:

对此锁解锁。

shared locking:

lock_shared:

获取互斥项的共享所有权。

try_lock_shared:

尝试在共享模式下锁定互斥。立即返回。成功锁定后返回 true,否则返回 false。即使互斥当前未被任何其他线程独占锁定,该函数也允许错误地失败并返回 false。

unlock_shared:

从调用线程的共享所有权中释放互斥。在共享模式下,mutex 必须被当前执行线程锁定,否则其行为将是未定义的。

std::shared_timed_mutex

和std::shared_mutex相似,相比于它,没有native_handle()这样获取底层资源的函数,且多了这四个参数:

try_lock_for:

尝试获取互斥量的锁。阻塞直到指定的持续时间 timeout_duration 经过(超时)或者成功获取锁(拥有互斥量),以先到者为准。如果成功获取锁,则返回 true,否则返回 false。由于调度或资源争用延迟,此函数可能会阻塞超过 timeout_duration 的时间。与 try_lock() 类似,即使在 timeout_duration 的某个时间点上互斥量没有被其他线程锁定,此函数也可以出现虚假失败并返回 false。

try_lock_until:

尝试获取互斥量的锁。阻塞直到达到指定的超时时间 timeout_time(到达超时)或成功获取锁(拥有互斥量),以先到者为准。如果成功获取锁,则返回 true,否则返回 false。如果超时时间 timeout_time 已经过去,则此函数的行为类似于 try_lock()。与 try_lock() 类似,即使在超时时间之前互斥量没有被其他线程锁定,该函数也可以出现虚假失败并返回 false。

try_lock_shared_for:

与try_lock_for类似,只是获取的是共享锁。

try_lock_shared_until:

与try_lock_until类似,只是获取的是共享锁。

锁管理

std::lock_guard

lock_guard 类是一个互斥包装器, 当创建 lock_guard 对象时,它会尝试获取所给互斥的所有权。当控制权离开创建 lock_guard 对象的作用域时,lock_guard 会被析构,mutex 也会被释放。lock_guard类不可被拷贝,没有赋值运算符。

它的模板参数必须符合BasicLockable要求。

构造函数:

  1. 接受一个锁参数,然后立刻调用其lock()成员函数。
  2. 获取 mutex m 的所有权,但不试图锁定它。如果当前线程未持有 m 上的非共享锁,则该行为未定义。

析构函数:

调用拥有的锁的unlock()。

std::unique_lock

unique_lock是一个通用的互斥量所有权包装器,允许延迟锁定、限时尝试锁定、递归锁定、锁的所有权转移以及与条件变量一起使用。类unique_lock是可移动的,但不可复制。

构造函数:

  1. 默认构造函数,构造一个没有关联互斥量的对象。
  2. 移动构造函数,用其他对象的内容初始化unique_lock对象,同时将其他对象置为没有关联互斥量。
  3. 使用互斥量m构造一个关联的unique_lock对象,然后可以通过选择是否传参以及传递什么参数,使互斥量被锁定、不锁定、调用try_lock()锁定、认为互斥量是非共享锁定状态的、调用try_lock_for或调用try_lock_until的。

析构函数:

如果 *this 有关联的互锁体,并且已获得其所有权,则互锁体被解锁。

移动赋值操作符:

使用移动语义将内容替换为其他内容。如果在调用 *this 之前已关联了一个互斥项并获得了它的所有权,则互斥项将被解锁。

Locking:

lock:

锁定拥有的互斥。实际上是调用拥有互斥的lock成员函数。

try_lock:

尝试在不阻塞的情况下锁定(即获取)相关的互斥。实际上是调用 mutex()->try_lock()。

try_lock_for:

实际上调用了 mutex()->try_lock_for(timeout_duration)。

try_lock_until:

实际上调用了 mutex()->try_lock_until(timeout_time)。

unlock:

解锁。实际上调用了mutex()->unlock();

Modifiers:

swap;

交换锁对象的内部状态。

release():

中断相关互斥(如果有)与 *this 的关联。不会解锁任何锁。

Observers:

mutex();

返回指向相关静态代理的指针,如果没有相关静态代理,则返回空指针。

owns_lock();

检查 *this 是否拥有锁定的互斥。

std::shared_lock

shared_lock是一个通用的共享互斥量所有权包装器,允许延迟锁定、定时锁定和锁的所有权转移。通过对shared_lock进行锁定,将以共享模式锁定关联的共享互斥量. shared_lock类是可移动的,但不可复制。

构造函数:

  1. 默认构造函数,构造一个没有关联互斥量的对象。
  2. 移动构造函数,用其他对象的内容初始化shared_lock对象,同时将其他对象置为没有关联互斥量。
  3. 使用互斥量m构造一个关联的shared_lock对象,然后可以通过选择是否传参以及传递什么参数,使互斥量以共享模式被锁定、不锁定、调用try_lock_shared()锁定、认为互斥量是共享锁定状态的、调用try_lock_shared_for或调用try_lock_shared_until的。

析构函数:

如果 *this 有关联的互锁体,并且已获得其所有权,则通过调用 unlock_shared() 来解锁互锁体。

赋值运算符:

使用移动语义将内容替换为其他内容。如果在调用 *this 之前已关联了一个互斥项并获得了它的所有权,则会通过调用 unlock_shared() 来解锁互斥体。

Locking:

lock:

以共享模式锁定相关的互斥。实际上是调用拥有互斥的lock_shared成员函数。

try_lock:

尝试在不阻塞的情况下以共享模式锁定相关的互斥。实际上是调用 mutex()->try_lock_shared()。

try_lock_for:

实际上调用了 mutex()->try_lock_shared_for(timeout_duration)。

try_lock_until:

实际上调用了 mutex()->try_lock_shared_until(timeout_time)。

unlock:

解锁。实际上调用了mutex()->unlock_shared();

Modifiers:

swap;

交换锁对象的内部状态。

release():

中断相关互斥(如果有)与 *this 的关联。不会解锁任何锁。

Observers:

mutex();

返回指向相关静态代理的指针,如果没有相关静态代理,则返回空指针。

owns_lock();

检查 *this 是否拥有共享互斥量的共享所有权。

std::scoped_lock

scoped_lock是一个互斥量包装器, 用于在作用域块的持续时间内拥有零个或多个互斥量。如果给定了多个互斥量,则会使用避免死锁的算法,类似于std::lock的行为。scoped_lock类是不可复制的。

构造函数:

  1. 获取给定互斥量的所有权,即调用对应的lock成员函数。
  2. 在不尝试锁定任何互斥量的情况下获取互斥量 m... 的所有权。除非当前线程对 m... 中的每个对象都持有非共享锁,否则行为是未定义的。

析构函数:

释放所有互斥的所有权,及调用每个互斥体的unlock()成员函数。

赋值运算符已经被删除。

Call once

call_once:

once_flag:

Condition variables

条件变量的唤醒丢失与虚假唤醒问题。

std::condition_variable

condition_variable 类是与 std::mutex 一起使用的同步原语,用于阻塞一个或多个线程,直到另一个线程修改了共享变量(条件)并通知 condition_variable。std::condition_variable仅适用于std::unique_lockstd::mutex,这样可以在某些平台上实现最高效率。

它不可被移动或复制。

构造函数:

默认构造函数,构造一个std::condition_variable对象。

析构函数:

销毁 std::condition_variable 类型的对象。只有在所有线程都已被通知的情况下才能安全地调用析构函数。

Notification:

notify_one():

如果有线程正在等待 *this,调用 notify_one 会解除其中一个等待线程的阻塞。

notify_all():

解除当前等待 *this 的所有线程的阻塞。

Waiting:

wait:

wait 函数会导致当前线程阻塞,直到条件变量被通知或出现虚假唤醒。它有两个重载。

  1. 只有参数锁:原子性地解锁 lock,阻塞当前执行的线程,并将其添加到等待 *this 的线程列表中。它被唤醒而解除阻塞时,都会重新获取互斥锁并退出 wait 函数。
  2. 有参数锁和谓词:等价于如下代码:
while (!stop_waiting()) {  // stop_waiting函数是谓词wait(lock);
}

这个重载函数可以避免虚假唤醒的问题。

这里的锁必须是std::unique_lockstd::mutex

wait_for: wait_until:

前者是最多阻塞的相对超时时间,后者是最多阻塞到某个时间点。它们其余部分和wait一致。

Native handle:

native_handle():访问 *this 的本地句柄。

std::condition_variable_any

class condition_variable_any 是 std::condition_variable 的一个更通用的版本。而 std::condition_variable 只能与 std::unique_lockstd::mutex 一起使用,condition_variable_any 可以操作任何满足 BasicLockable 要求的锁。

class std::condition_variable_any 是一个 StandardLayoutType。它不可被移动或复制。

如果锁是 std::unique_lockstd::mutex,则 std::condition_variable 可能提供更好的性能。

下面列出些std::condition_variable没有的功能:

wait;wait_for; wait_until:

都多了第三个重载,多了一个stoken变量:多了一个 std::stop_token 对象,用于支持取消等待操作。当外部发出取消请求时,可以通过该对象检查并中止等待。

Latches and Barriers

Futures

Futures 功能是并发编程机制,旨在简化多线程编程和异步操作的处理。Futures 提供了一种在一个线程中计算值或执行任务,并在另一个线程中获取结果的方法。

它的核心组件时std::futurestd::promisestd::future 对象与 std::promise 对象之间共享一个状态。通过 std::promise 对象设置的值可以通过与其关联的 std::future 对象来获取。这样就可以使一个线程使用 std::promise 对象来设置异步操作的结果,而另一个线程使用对应的 std::future 对象来获取结果。

std::futuer

std::future提供了一种访问异步操作结果的机制, 通过std::async、std::packaged_task或std::promise创建的异步操作可以向该异步操作的创建者提供一个std::future对象。异步操作的创建者可以使用各种方法来查询、等待或从std::future中提取值。

构造函数:

  1. 默认构造函数,创建一个没有共享状态的 std::future 对象。
  2. 移动构造函数,构造后,被移动的对象没有共享状态
  3. 拷贝构造函数被删除。

析构函数:

释放任何共享状态不会阻塞等待共享状态变为就绪,除非以下所有条件都成立时可能会阻塞:(一定会阻塞吗?????)

  • 共享状态是通过调用 std::async 创建的。
  • 共享状态尚未就绪。
  • 当前对象是对共享状态的最后一个引用。

这些操作只有在任务的启动策略为 std::launch::async 时才会阻塞

只有移动赋值运算符,没有拷贝赋值运算符。移动后,被移动的对象没有共享状态。

share():

将 *this 的共享状态(如果有的话)转移给一个 std::shared_future 对象。在调用 share 后,valid() == false

Getting the result:

get():

阻塞当前线程,直到future准备妥当并返回该值,或者抛出异步运行的函数的异常或被设置的异常. 在调用此成员函数后,共享状态会被释放, valid() 为 false。如果在调用此函数之前 valid() 为 false,则行为是未定义的。

State:

valid:

检查 future 是否引用共享状态。

wait:

阻塞直到结果变为可用。

wait_for:

等待结果变为可用。阻塞直到指定的 timeout_duration 经过或结果可用,以先到者为准。返回值标识结果的状态。如果 future 是通过使用lazy evaluation的方式调用 std::async 的结果,该函数会立即返回而不等待。

wait_until:

wait_until 函数等待结果变为可用。它会阻塞直到达到指定的 timeout_time 或结果可用,以先到者为准。返回值指示 wait_until 返回的原因。如果 future 是通过使用lazy evaluation的方式调用 std::async 的结果,该函数会立即返回而不等待。

std::shared_future

std::shared_future类似于 std::future,但允许多个线程等待相同的共享状态。std::shared_future 是既可移动,也可复制的,多个共享的 std::shared_future 对象可以引用相同的共享状态。通过各自的 std::shared_future 对象,多个线程可以安全地访问相同的共享状态。

构造函数:

  1. 默认构造函数。构造一个空的shared_future, 不引用共享状态。
  2. 拷贝构造函数,构造一个引用与other相同共享状态(如果有的话)的shared_future.
  3. 移动构造函数,将 other 持有的共享状态转移给 *this。构造后,other.valid() == false,且 this->valid() 的返回值与在构造之前 other.valid() 的返回值相同。

赋值运算符:

  1. 拷贝赋值运算符:1. 释放任何共享状态,并将 other 的内容赋值给 *this。赋值后,this->valid() == other.valid()
  2. 移动赋值运算符:1. 释放任何共享状态,并将 other 的内容移动赋值给 *this。赋值后,other.valid() == false,并且 this->valid() 的返回值与赋值之前的 other.valid() 的返回值相同。

Getting the result:

get:

get 成员函数会等待直到 shared_future 有一个有效的结果,并且(根据使用的模板)获取它。它实际上会调用 wait() 来等待结果。与 std::future 不同,当调用 get() 时,std::shared_future 的共享状态不会无效。

State:

valid();

检查 shared_future 是否引用共享状态。

wait():

调用后 valid() == true。如果在调用此函数之前 valid() == false,则行为未定义。

wait_for();

等待结果可用。阻塞直到指定的 timeout_duration 已过或结果可用,以先到者为准。返回值标识结果的状态。如果 future 是调用 std::async 并使用了懒评估的结果,则此函数无需等待,立即返回。

wait_until();

wait_until 等待结果可用。它会阻塞,直到达到指定的 timeout_time 或结果可用为止,以先到者为准。返回值说明 wait_until 返回的原因。如果 future 是调用 async 时使用了懒评估的结果,则此函数会立即返回而无需等待。

std::async()

函数模板 std::async 异步地运行函数 f(可能在一个独立的线程中,该线程可能是线程池的一部分),并返回一个 std::future,最终将保存该函数调用的结果。它可以根据系统情况自动选择是独立启动一个线程运行,还是在对应的future调用get时运行;也可以由调用者指定任务调用策略。

任务调用策略:

  1. std::launch::async; 开启一个独立线程执行任务
  2. std::launch::deferred; 使用延迟批评估。

请注意,除了调用 std::async 之外,通过其他方式获得的 std::futures 的析构函数永远不会阻塞。

构造函数:

  1. 不加策略的构造函数
  2. 加策略的构造函数

std::package_task<>

类模板 std::packaged_task 可以封装任何可调用目标,以便可以异步调用它。它的返回值或抛出的异常被存储在一个共享状态中,可以通过 std::future 对象访问该状态。它不可被复制。

默认构造函数:

  1. 构造一个没有任务和共享状态的 std::packaged_task 对象。
  2. 构造一个具有共享状态和任务副本的 std::packaged_task 对象,使用 std::forward<F>(f) 进行初始化。
  3. 复制构造函数被删除,std::packaged_task 是只可移动的
  4. 移动构造函数,构造一个具有共享状态和任务的 std::packaged_task,该状态和任务原先由 rhs 拥有,将 rhs 置于无共享状态和已移动的任务状态。

析构函数:

放弃共享状态并销毁存储的任务对象。如果共享状态在准备就绪之前被放弃,则会存储一个 std::future_error 异常,错误代码为 std::future_errc::broken_promise。

复制运算符:

只有移动赋值运算符。移动赋值运算符:释放共享状态(如果有),销毁之前持有的任务,并将共享状态和 rhs 拥有的任务移入 *this。

valid();

检查是否有一个共享状态,即是否包含一个有效的任务。

swap():

将"*this"和"other"的共享状态和存储的任务进行交换。

Getting the result:

get_future:

用于获取一个 std::future 对象,该对象与当前 std::packaged_task 共享相同的共享状态。get_future() 函数只能调用一次.

Execution:

operator():

执行存储中的任务。任务的返回值或抛出的任何异常都会存储在共享状态中。

make_ready_at_thread_exit:

共享状态只有在当前线程退出并且所有具有线程局部存储期的对象被销毁后,才会准备就绪。

reset():

重置状态,放弃之前的执行结果。构建新的共享状态。

std::promise<>

类模板 std::promise 提供了一种存储值或异常的机制,这些值或异常可以通过由 std::promise 对象创建的 std::future 对象在异步方式下获取。std::promise 对象只能使用一次,因此不可被复制。

每个 promise 关联一个共享状态, 它可以对共享状态执行三种操作:

  1. 准备就绪:
    promise 将结果或异常存储在共享状态中。标记状态为就绪,并解除任何等待与共享状态相关联的 future 的线程的阻塞。
  2. 释放:
    promise 放弃对共享状态的引用。如果这是最后一个对共享状态的引用,那么共享状态将被销毁。
  3. 放弃:
    promise 将类型为 std::future_error,错误代码为 std::future_errc::broken_promise 的异常存储在共享状态中,使共享状态变为就绪状态,然后释放它。

构造函数:(拷贝构造函数被删除)

  1. 默认构造函数。使用空的共享状态构造promise。
  2. 移动构造函数。使用移动语义构造 promise,使用其他 promise 的共享状态。构造完成后,其他 promise 不再具有共享状态。

析构函数:

  1. 如果共享状态已就绪,则释放共享状态。
  2. 如果共享状态未就绪,则存储一个 std::future_error 类型的异常对象(错误条件为 std::future_errc::broken_promise),使共享状态就绪并释放它。

赋值运算符:(没有拷贝运算符)

移动赋值操作符。首先,放弃共享状态,然后通过执行 std::promise(std::move(other)).swap(*this) 赋值给 other 的共享状态。

Getting the result:

get_future:

返回与 *this 相同共享状态相关联的std::future。

set_value; set_value_at_thread_exit;

原子式地将值存储到共享状态中,并使状态就绪。如果没有共享状态或共享状态已存储值或异常,则会抛出异常。

前者是立即让共享状态就绪,后者是等当前线程退出时,所有具有线程本地存储期限的变量都已销毁,状态才会就绪。

set_exception; set_exception_at_thread_exit;

除了存储的是异常,其余和set_value; set_value_at_thread_exit;完全一致。

set_value: 保存值

set_exception: 保存异常

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

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

相关文章

内部类 --java学习笔记

内部类 是类中的五大成分之一&#xff08;成员变量、方法、构造器、内部类、代码块&#xff09;&#xff0c;如果一个类定义在另一个类的内部&#xff0c;那么这个类就是内部类当一个类的内部包含了一个整体的事务&#xff0c;且这个事务没必要单独设计时&#xff0c;就可以把…

(十三)centos7案例实战——用户、用户组及用户权限管理

前言 对于完备的centos系统来说&#xff0c;创建一套规范的账户权限系统是十分必要的。针对不同的用户提供不同的操作权限&#xff0c;避免直接使用root账号&#xff0c;造成系统的误操作&#xff0c;导致一些不必要的损失&#xff0c;将删库跑路扼杀在摇篮中。本节内容会从用…

基于springboot校园台球厅人员与设备管理系统源码和论文

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括校园台球厅人员与设备管理系统的网络应用&#xff0c;在外国管理系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。校园台球厅人员与设备管理系统具…

五、C#与数据库交互(数据存储过程与触发器)

在C#中与数据库交互时&#xff0c;除了基本的查询和更新操作&#xff0c;还经常需要使用存储过程和触发器。下面我将简要介绍如何在C#中使用存储过程和触发器。 存储过程 存储过程是一组为了完成特定功能的SQL语句集&#xff0c;它可以被存储在数据库中&#xff0c;并可以被调…

Fastbee物联网项目新手快速入门

一&#xff0c;前提条件 后端环境准备如下&#xff1a; 正式环境推荐硬件资源最低要求4c8G&#xff0c;硬盘40G。JDK 1.8.0_2xx (需要小版本号大于200) 。Maven3.6.3。&#xff08;IDEA启动时使用IDEA默认自带的版本即可&#xff09;。 启动fastbee之前&#xff0c;请先确定…

课时6:编程语言逻辑

1.2.2 编程语言逻辑 学习目标 这一节&#xff0c;我们从 语言分类、编程逻辑、小结 三个方面来学习。 语言分类 语言分类 低级编程语言&#xff1a;机器&#xff1a;- 二进制的0和1的序列&#xff0c;称为机器指令。- 一般人看不懂汇编&#xff1a;- 用一些助记符号替代机…

LPC804开发(4.ctimer使用)

1.前言 昨天晚上画完板子&#xff0c;还剩点时间就再翻了翻手册&#xff0c;大致清楚了时钟树的运行&#xff0c;顺带搞清楚了定时的使用&#xff0c;那就出一份教程吧。 如果各位在此之前没有接触过LPC单片机&#xff0c;还是建议先把程序直接贴进自己的项目&#xff0c;稍微…

“拔叔”的新片又杀疯了!

近&#xff0c;“拔叔”麦斯米科尔斯的新片登上口碑榜。 该片曾入围去年威尼斯金狮奖&#xff0c;上映后颇受好评&#xff0c;目前豆瓣评分8.2分。 将代表丹麦角逐2024年奥斯卡最佳外语片&#xff0c;目前已入15强。 作为“丹麦最性感的男人”&#xff0c;拔叔的实力不容小觑。…

Logistics 逻辑回归概念

1. sigmoid函数 逻辑回归算法的拟合函数&#xff0c;叫做sigmoid函数&#xff1a; 函数图像如下&#xff08;百度图片搜到的图&#xff09;&#xff1a; sigmoid函数是一个s形曲线&#xff0c;就像是阶跃函数的温和版&#xff0c;阶跃函数在0和1之间是突然的起跳&#xff0c;…

Spring Boot常用的注解有哪些

Spring Boot常用的注解有&#xff1a; SpringBootApplication&#xff1a;用于标记Spring Boot应用的主类&#xff0c;通常放在启动类上&#xff0c;相当于同时使用Configuration、EnableAutoConfiguration和ComponentScan。 ComponentScan&#xff1a;用于自动扫描并注册Bean…

刷题09 双指针

2540. 最小公共值 给你两个整数数组 nums1 和 nums2 &#xff0c;它们已经按非降序排序&#xff0c;请你返回两个数组的 最小公共整数 。如果两个数组 nums1 和 nums2 没有公共整数&#xff0c;请你返回 -1 。 如果一个整数在两个数组中都 至少出现一次 &#xff0c;那么这个整…

std::for_each

std::for_each 是 C STL 中的标准函数之一&#xff0c;用于对指定的容器或序列中的元素执行指定的操作。该函数的头文件为 <algorithm>&#xff0c;定义在 namespace std 中&#xff0c;因此需要包含该头文件才能使用该函数。 std::for_each 函数是 C STL 中自 C98 就开…

「优选算法刷题」:汉明距离

一、题目 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 示例 1&#xff1a; 输入&#xff1a;x 1, y 4 输出&#xff1a;2 解释&#xff1a; 1 (0 0 0 1) 4 (0 1 0 0)↑ …

【JavaSE篇】——类和对象

目录 &#x1f393;类定义和使用 &#x1f393;简单认识类 &#x1f6a9;类的定义格式 ❗注意事项 &#x1f393;类的实例化 &#x1f6a9;什么是实例化 &#x1f6a9;类和对象的说明 &#x1f393;this引用 &#x1f6a9;为什么要有this引用 &#x1f6a9;什么是thi…

【JavaScript 基础入门】02 JavaScrip 详细介绍

JavaScrip 详细介绍 目录 JavaScrip 详细介绍1. JavaScript 是什么2. JavaScript的作用3. HTML/CSS/JS 的关系4. 浏览器执行 JS 简介5. JavaScript 的组成6. JavaScript 的特点 1. JavaScript 是什么 JavaScript&#xff0c;通常缩写为 JS&#xff0c;是一种高级的&#xff0c;…

分布式技术浅见之复制

分布式技术浅见之复制 前言一、何为复制&#xff1f;1.1 主从复制和无主从复制1.2 同步复制与异步复制1.3 来点栗子1.3.1 Redis1.3.2 Mysql1.3.3 Mongo 二、复制是如何实现的&#xff1f;2.1 复制的过程2.2 来点栗子2.2.1 Redis2.2.2 Mysql2.2.3 Mongo 2.2 复制的实现方式2.4 举…

OpenHarmony—不支持解构赋值

规则&#xff1a;arkts-no-destruct-assignment 级别&#xff1a;错误 ArkTS不支持解构赋值。可使用其他替代方法&#xff0c;例如&#xff0c;使用临时变量。 TypeScript let [one, two] [1, 2]; // 此处需要分号 [one, two] [two, one];let head, tail [head, ...tail]…

MySQL十部曲之六:数据操作语句(DML)

文章目录 前言语法约定DELETEINSERTSELECT查询列表SELECT 选项子句FROMWHEREORDER BYGROUP BYHAVINGWINDOWLIMITFOR SELECT ... INTO连接查询CROSS JOIN和INNER JOINON和USINGOUTER JOINNATURE JOIN 子查询标量子查询使用子查询进行比较带有ANY、IN或SOME的子查询带有ALL的子查…

DETR解读,将Transformer带入CV

论文出处 [2005.12872] End-to-End Object Detection with Transformers (arxiv.org) 一个前置知识 匈牙利算法&#xff1a;来源于二部图匹配&#xff0c;计算最小或最大匹配 算法操作&#xff1a;在n*n的矩阵中 减去行列最小值&#xff0c;更新矩阵&#xff08;此时行或者…

搜维尔科技:【简报】元宇宙数字人赛道,优秀作品赏析《大福太郎》

这次采用亮眼的浅粉做为发色&#xff0c;为了贴合她小警察的身分 给了她一顶特制的警帽&#xff0c;上面有大福的荧光蓝叶片作为标 志&#xff0c;而在配件及裙子上也加入了许多科技元素的小巧思。 学校&#xff1a; 朝阳科技大学&#xff08;台湾&#xff09; 选手&#xff…