网站模板案例怎么建立信息网站平台

web/2025/10/3 0:13:48/文章来源:
网站模板案例,怎么建立信息网站平台,宁波市网站制作,wordpress搬家简书1 std::mutex 的基础概念 1.1 std::mutex 的定义与声明 std::mutex 是 C11 标准库中的一个互斥量#xff08;mutex#xff09;类#xff0c;用于保护共享资源的并发访问。在多线程环境中#xff0c;当多个线程试图同时访问和修改同一资源时#xff0c;可能会发生数据竞争…1 std::mutex 的基础概念 1.1 std::mutex 的定义与声明 std::mutex 是 C11 标准库中的一个互斥量mutex类用于保护共享资源的并发访问。在多线程环境中当多个线程试图同时访问和修改同一资源时可能会发生数据竞争和不一致的问题。std::mutex 提供了一种机制使得同一时间只有一个线程能够访问被保护的资源。 定义 std::mutex 是一个类它定义在 mutex 头文件中。要使用 std::mutex需要包含这个头文件。这个类提供了互斥锁的基本功能以及管理锁状态的机制。 声明 声明一个 std::mutex 对象非常简单。只需要在代码中创建一个该类型的变量即可。例如 #include mutex std::mutex mtx; // 声明一个互斥量对象 mtx在上面的代码中mtx 是一个 std::mutex 类型的对象。这个对象在创建时处于解锁状态表示它当前没有锁定任何资源。 特点 互斥性std::mutex 提供了互斥锁的基本功能即同一时间只允许一个线程访问被保护的共享资源。当一个线程获取了互斥锁后其他试图获取该锁的线程会被阻塞直到该线程释放锁。不可复制性std::mutex 对象是不可复制的。这是为了确保互斥锁的所有权在不同线程之间正确传递防止同一个互斥锁对象被多个线程同时持有。可移动性虽然 std::mutex 对象不可复制但它是可移动的。这意味着可以通过移动语义来转移互斥锁的所有权。这在某些情况下是有用的比如当需要在容器或智能指针中存储互斥锁时。 成员函数 std::mutex 类提供了几个成员函数来管理锁的状态 构造函数创建一个新的 std::mutex 对象该对象在创建时处于解锁状态。lock()尝试锁定互斥量。如果互斥量当前没有被锁定则锁定它并立即返回。如果互斥量已经被另一个线程锁定则当前线程会被阻塞直到互斥量变得可用并被当前线程锁定。unlock()解锁之前由同一线程锁定的互斥量。如果互斥量没有被当前线程锁定则行为是未定义的。try_lock()在 std::timed_mutex 或 std::recursive_timed_mutex 中提供尝试锁定互斥量如果互斥量已被另一个线程锁定则不会阻塞当前线程而是立即返回表示是否成功锁定的结果。 使用 std::mutex 时通常建议与 std::lock_guard 或 std::unique_lock 结合使用它们提供了 RAIIResource Acquisition Is Initialization风格的锁管理可以确保在离开作用域时自动释放锁从而避免忘记解锁而导致的问题。 1.2 std::mutex 的状态与行为 状态 std::mutex 有两种基本状态锁定状态和未锁定状态。 未锁定状态这是 std::mutex 对象在创建后的初始状态也是每次调用 unlock() 方法后的状态。在未锁定状态下任何线程都可以尝试获取互斥锁。锁定状态当一个线程成功调用 lock() 方法后std::mutex 对象会进入锁定状态。在锁定状态下其他试图调用 lock() 方法的线程将被阻塞直到互斥锁被当前持有者释放即调用 unlock() 方法。 行为 std::mutex 的行为主要通过其成员函数来体现这些函数允许线程获取和释放互斥锁。 1构造函数和析构函数 构造函数会初始化 std::mutex 对象将其设置为未锁定状态。析构函数会自动释放互斥锁如果它被锁定的话确保在对象销毁时不会发生悬挂锁或死锁。 2lock() 当一个线程调用 lock() 方法时如果 std::mutex 对象当前处于未锁定状态该线程将成功获取互斥锁并将互斥锁状态设置为锁定。如果 std::mutex 对象已经被另一个线程锁定调用 lock() 的线程将被阻塞直到互斥锁被释放。 3unlock() 调用 unlock() 方法会释放由当前线程持有的 std::mutex 对象。这会将互斥锁的状态从锁定更改为未锁定并允许其他线程获取该锁。如果当前线程没有锁定 std::mutex 对象调用 unlock() 方法是未定义行为通常会导致程序崩溃。 4try_lock()在 std::timed_mutex 或其他相关类型中提供 尝试获取互斥锁而不会阻塞当前线程。如果互斥锁当前可用即处于未锁定状态则获取锁并返回 true否则不阻塞并立即返回 false。 注意事项 std::mutex 不支持递归锁定即同一个线程不能多次锁定同一个 std::mutex 对象而没有相应的解锁操作。这样做会导致未定义行为通常是死锁。线程在持有 std::mutex 锁时不应执行可能导致阻塞的操作如 I/O 操作或等待用户输入因为这可能会不必要地延长其他线程的等待时间。使用 std::mutex 时应始终确保配对使用 lock() 和 unlock()以避免资源泄漏或死锁。为此建议使用 std::lock_guard 或 std::unique_lock它们会在构造时自动锁定互斥量并在析构时自动解锁从而简化锁的管理。 2 std::mutex 的使用 2.1 lock() 与 unlock() 函数 std::mutex 类中的 lock() 和 unlock() 函数是控制互斥量mutex锁定和解锁状态的关键方法。在多线程编程中这两个函数用于确保同一时间只有一个线程能够访问特定的共享资源从而避免数据竞争和不一致的问题。 lock() 函数 lock() 函数尝试获取互斥量的所有权。如果互斥量当前没有被其他线程锁定那么调用 lock() 的线程会成功获取互斥量并继续执行后续的代码。如果互斥量已经被其他线程锁定那么调用 lock() 的线程会被阻塞直到互斥量变为可用状态。 unlock() 函数 unlock() 函数用于释放先前通过 lock() 获取的互斥量。调用 unlock() 之后其他线程就可以尝试获取这个互斥量了。重要的是只有锁定了互斥量的线程才能调用 unlock()否则会导致未定义行为通常会导致程序崩溃。 示例 下面是一个简单的示例展示了如何使用 std::mutex 的 lock() 和 unlock() 函数来保护共享资源的访问 #include iostream #include thread #include mutex std::mutex mtx; // 全局互斥量 int shared_data 0; // 共享数据 void increment() {mtx.lock(); // 尝试获取互斥量 for (size_t i 0; i 5; i){shared_data; // 访问和修改共享数据 std::cout Thread std::this_thread::get_id() incremented shared_data to shared_data std::endl;}mtx.unlock(); // 释放互斥量 }int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout Final value of shared_data: shared_data std::endl;return 0; }上面代码的输出为 Thread 4936 incremented shared_data to 1 Thread 4936 incremented shared_data to 2 Thread 4936 incremented shared_data to 3 Thread 4936 incremented shared_data to 4 Thread 4936 incremented shared_data to 5 Thread 10384 incremented shared_data to 6 Thread 10384 incremented shared_data to 7 Thread 10384 incremented shared_data to 8 Thread 10384 incremented shared_data to 9 Thread 10384 incremented shared_data to 10 Final value of shared_data: 10这个示例定义了一个全局的 std::mutex 对象 mtx 和一个全局的整数 shared_data 作为共享资源。increment 函数尝试增加 shared_data 的值。在修改 shared_data 之前函数首先调用 mtx.lock() 来获取互斥量。如果互斥量已经被另一个线程锁定当前线程将会等待。一旦获取到互斥量线程就可以安全地修改 shared_data 了。修改完成后线程调用 mtx.unlock() 来释放互斥量这样其他线程就可以获取它并修改 shared_data 了。 2.2 调用线程的行为分析 1互斥量未被锁住时 当互斥量mutex未被锁住时任何线程都可以尝试调用lock()函数来获取互斥量的所有权。一旦线程成功获取到互斥量它将拥有对共享资源的独占访问权其他线程尝试调用lock()将阻塞直到当前线程释放互斥量。 示例代码 #include iostream #include thread #include mutex std::mutex mtx; // 全局互斥量 void safe_increment() { mtx.lock(); // 互斥量未被锁住线程将获取锁 static int counter 0; counter; std::cout Counter: counter std::endl; mtx.unlock(); // 释放锁 } int main() { std::thread t1(safe_increment); std::thread t2(safe_increment); t1.join(); t2.join(); return 0; }上面代码的输出为 Counter: 1 Counter: 2在这个例子中当 t1 和 t2 线程尝试调用 safe_increment 函数时互斥量 mtx 是未被锁住的。因此每个线程都会先获取互斥量然后安全地增加 counter 的值最后释放互斥量。这样就不会发生两个线程同时修改 counter 的情况从而避免了数据竞争。 2互斥量被其他线程锁住时 当互斥量已经被其他线程锁住时任何尝试调用 lock()的线程都会被阻塞直到拥有锁的线程调用 unlock() 释放互斥量。这种机制确保了同一时间只有一个线程能够访问受保护的共享资源。 示例代码 #include iostream #include thread #include mutex #include chrono std::mutex mtx; void long_operation() { mtx.lock(); std::cout Thread std::this_thread::get_id() is doing a long operation. std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟长时间操作 mtx.unlock(); } void another_operation() { std::cout Thread std::this_thread::get_id() is waiting for the mutex. std::endl; mtx.lock(); // 如果mtx已被其他线程锁住这里会阻塞 std::cout Thread std::this_thread::get_id() acquired the mutex. std::endl; mtx.unlock(); } int main() { std::thread t1(long_operation); std::thread t2(another_operation); t1.join(); t2.join(); return 0; }上面代码的输出为 Thread 9672 is doing a long operation.Thread 10244 is waiting for the mutex.Thread 10244 acquired the mutex.在这个例子中t1 线程首先获取了互斥量并执行长时间操作。当 t2 线程尝试获取互斥量时由于 mtx 已被 t1 线程锁住t2 线程会被阻塞直到 t1 线程释放互斥量。 3互斥量被当前线程锁住时死锁情况 当互斥量被当前线程锁住并且该线程再次尝试锁住同一个互斥量时会发生死锁。死锁是指两个或更多线程无限期地等待一个资源而该资源却被另一个线程持有导致所有线程都无法继续执行。在 C 中如果一个线程试图对一个已经被它锁住的互斥量再次调用 lock()那么行为是未定义的通常会导致程序崩溃或死锁。 为了避免死锁应该确保每个线程在完成对共享资源的访问后都释放互斥量并且不要在已经拥有锁的情况下再次尝试获取同一个锁。如果确实需要递归锁定应该使用 std::recursive_mutex 而不是 std::mutex。 示例代码错误用法会导致死锁 #include iostream #include thread #include mutex #include chrono std::mutex mtx; void deadlock_risk() { mtx.lock(); // ... do some work ... // 错误尝试再次锁住已经被当前线程锁住的互斥量 mtx.lock(); // 这将导致未定义行为通常是死锁 }int main() { std::thread t(deadlock_risk); t.join(); return 0; }3 RAII 风格的锁管理 3.1 std::lock_guard 的使用 std::lock_guard 是 C11 引入的一个模板类用于在作用域内自动管理互斥量mutex的加锁和解锁操作。它的主要目标是简化互斥量的管理避免由于异常或忘记解锁而导致的问题。通过使用 std::lock_guard可以确保在代码块结束时互斥量会被自动解锁即使发生异常也是如此。 下面是 std:: lock_guard 的使用方法和一些关键点 1包含头文件 首先需要包含 mutex 头文件来使用 std::lock_guard。 #include mutex2创建互斥量 在使用 std::lock_guard 之前需要创建一个互斥量mutex对象。 std::mutex mtx; // 全局或局部变量3使用 std::lock_guard 创建一个 std::lock_guard 对象时它会尝试锁定传入的互斥量。如果互斥量已经被其他线程锁定那么当前线程会阻塞直到互斥量被释放。 当 std::lock_guard 对象被创建时它的构造函数会自动调用 lock() 函数来锁定互斥量。当 std::lock_guard 对象离开其作用域例如在函数返回或块结束时时它的析构函数会自动调用 unlock() 函数来解锁互斥量。 下面是一个简单的使用示例 void safe_increment() { std::lock_guardstd::mutex lock(mtx); // 锁定互斥量 // 在这里执行对共享资源的访问 static int counter 0; counter; std::cout Counter: counter std::endl; // 无需手动解锁std::lock_guard会在离开作用域时自动解锁 }在上面的示例中safe_increment 函数使用 std::lock_guard 来确保对 counter 的访问是线程安全的。在 std::lock_guard 对象 lock 的生命周期内互斥量 mtx 被锁定从而防止其他线程同时访问 counter。当 lock 对象离开其作用域时即函数结束时互斥量自动解锁。 4异常安全性 std::lock_guard 的一个重要优点是它的异常安全性。即使在加锁后的代码块中抛出异常std::lock_guard 的析构函数仍然会确保互斥量被正确解锁。这使得使用 std::lock_guard 的代码更加健壮和易于管理。 5注意事项 std::lock_guard 对象不能被复制或移动因此它们通常作为局部变量在需要保护的代码块中使用。一旦 std::lock_guard 对象被创建并锁定了一个互斥量就不能再手动解锁该互斥量。解锁操作会在 std::lock_guard 对象析构时自动发生。如果需要更复杂的锁管理例如同时锁定多个互斥量可能需要使用其他机制如 std::lock 函数或 std::unique_lock。 3.2 std::unique_lock 的使用与优势 std::unique_lock 是 C11 引入的一个模板类它提供了一种灵活的方式来管理互斥量mutex的锁定和解锁操作。与 std::lock_guard 相比std::unique_lock 提供了更多的控制选项使得在复杂的并发编程场景中能够更精细地管理锁。 下面是 std:: unique_lock 的使用方法和一些关键点 1包含头文件 首先需要包含 mutex 头文件来使用 std::unique_lock。 #include mutex2创建互斥量 在使用std::unique_lock之前你需要创建一个互斥量对象。 std::mutex mtx; // 互斥量对象3创建std::unique_lock对象 将互斥量对象传递给 std::unique_lock 的构造函数来创建一个 std::unique_lock 对象。这会自动尝试锁定互斥量。 std::unique_lockstd::mutex lock(mtx); // 锁定互斥量此时互斥量mtx被lock对象锁定其他线程无法获得该锁。 4手动控制锁定和解锁 与 std::lock_guard 不同std::unique_lock 允许在其生命周期内手动控制锁定和解锁。 lock.lock(); // 手动锁定互斥量 // 临界区代码 lock.unlock(); // 手动解锁互斥量如果希望在某个特定的作用域内锁定互斥量并在离开作用域时自动解锁可以将 lock.lock() 和 lock.unlock() 调用放在该作用域内。 5自动管理 尽管提供了手动控制的功能但 std::unique_lock 仍然支持自动管理锁定和解锁。当 std::unique_lock 对象离开其作用域例如在大括号结束时时其析构函数会自动调用 unlock() 来解锁互斥量。 { std::unique_lockstd::mutex lock(mtx); // 自动锁定 // 临界区代码 // 当离开这个作用域时lock对象会自动解锁互斥量 }6独特功能 除了基本的锁定和解锁功能外std::unique_lock还提供了一些独特的功能 延迟锁定 可以创建一个 std::unique_lock 对象但不立即锁定互斥量。这可以通过在构造函数中使用 std::defer_lock 标签来实现。 std::unique_lockstd::mutex lock(mtx, std::defer_lock); // 创建但不锁定 lock.lock(); // 稍后手动锁定尝试锁定 使用 try_lock() 成员函数尝试锁定互斥量如果互斥量已被其他线程锁定则不会阻塞当前线程而是立即返回。 if (lock.try_lock()) { // 成功锁定执行临界区代码 lock.unlock(); // 记得解锁 } else { // 未能锁定执行其他操作 }与条件变量配合使用 std::unique_lock 经常与 std::condition_variable 一起使用以实现线程间的同步。std::condition_variable 的某些成员函数如 wait()和 wait_for()需要 std::unique_lock 作为参数。 std::condition_variable cv; std::mutex mtx; std::unique_lockstd::mutex lock(mtx); cv.wait(lock, []{ /* 等待条件成立 */ }); // 使用unique_lock作为参数7总结 std::unique_lock 为 C 的并发编程提供了灵活且强大的锁管理功能。它支持自动和手动锁定和解锁允许延迟锁定和尝试锁定并能与条件变量配合使用从而在处理复杂的并发情况时提供了更多的选择和便利。选择使用 std::unique_lock 还是 std::lock_guard 取决于具体的应用场景和需求。在需要更多控制和灵活性时std::unique_lock 通常是更好的选择。 4 定时锁 std::timed_mutex std::timed_mutex 是 C11 标准库中引入的一种特殊的互斥量mutex类型它允许线程在尝试获取锁时设置一个超时时间。这种机制在多线程编程中特别有用因为它可以防止线程因长时间等待锁而导致的性能下降或死锁情况。 std::timed_mutex的主要特点 超时锁定与普通的 std::mutex 不同std::timed_mutex 提供了 try_lock_for 和 try_lock_until 两个成员函数允许线程在指定的时间段内尝试获取锁。如果在这个时间段内未能获取到锁线程可以选择放弃并继续执行其他操作而不是无限期地等待。灵活性通过设定超时时间std::timed_mutex 为线程提供了更多的灵活性。线程可以根据需要调整超时时间以适应不同的并发场景和性能要求。线程安全std::timed_mutex 满足定时互斥体TimedMutex的所有要求并确保了线程安全。它的复制构造函数已被删除以防止不当的复制操作。 std::timed_mutex的成员函数 try_lock_for(const std::chrono::durationRep, Period rel_time): 尝试在给定的时间段内获取锁。如果成功获取到锁则返回true否则在超时后返回false。try_lock_until(const std::chrono::time_pointClock, Duration abs_time): 尝试在指定的时间点之前获取锁。如果成功获取到锁则返回true否则在到达指定时间点后返回false。 使用示例 下面是一个简单的示例展示了如何使用std::timed_mutex #include iostream #include thread #include mutex #include chrono std::timed_mutex mtx; // 创建一个 timed_mutex 对象 void worker() { if (mtx.try_lock_for(std::chrono::milliseconds(100))) { // 尝试获取锁超时时间为100毫秒 std::cout Thread std::this_thread::get_id() acquired the mutex. std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟临界区操作耗时1秒 mtx.unlock(); // 解锁 } else { std::cout Thread std::this_thread::get_id() failed to acquire the mutex within the timeout. std::endl; } } int main() { std::thread t1(worker); std::thread t2(worker); t1.join(); t2.join(); return 0; }上面代码的输出为 Thread 1032 acquired the mutex. Thread 10300 failed to acquire the mutex within the timeout.这个示例创建了一个 std::timed_mutex 对象mtx并在 worker 函数中尝试使用 try_lock_for 函数获取锁。这里设置了 100 毫秒的超时时间。如果线程在 100 毫秒内成功获取到锁它将执行临界区代码这里用 std::this_thread::sleep_for 模拟了一个耗时操作然后解锁。如果线程在超时时间内未能获取到锁它将输出一条失败的消息。 5 递归锁 std::recursive_mutex std::recursive_mutex 是 C11 标准库中引入的一种特殊类型的互斥量mutex它允许同一线程多次获取同一个锁而不会引起死锁。这在某些递归函数或者需要多次锁定同一资源的场景中非常有用。普通的 std::mutex 是不允许同一线程多次锁定的如果尝试这样做将会导致未定义行为通常是死锁。 std::recursive_mutex 的主要特点 递归锁定同一线程可以多次调用 lock() 或 try_lock() 方法而不会导致死锁。每次 lock() 调用都需要有一个对应的 unlock() 调用以确保最终锁会被完全释放。线程安全与所有互斥量一样std::recursive_mutex 是线程安全的可以在多线程环境中安全使用。性能考虑由于 std::recursive_mutex 比 std::mutex 提供了更多的功能因此可能在某些情况下会有稍微的性能开销。在设计并发系统时应尽量避免不必要的递归锁定因为它可能导致更复杂的同步问题。 std::recursive_mutex 的成员函数 lock(): 尝试锁定互斥量。如果互斥量已被锁定则调用线程将阻塞直到锁被释放。unlock(): 解锁互斥量。只有锁定它的线程才能解锁它。try_lock(): 尝试非阻塞地锁定互斥量。如果互斥量已被锁定则立即返回并指示失败。 使用示例 下面是一个简单的示例展示了如何使用 std::recursive_mutex #include iostream #include thread #include mutex std::recursive_mutex mtx; // 创建一个递归互斥量对象 // 一个递归函数需要多次锁定相同的互斥量 void recursive_function(int depth) { mtx.lock(); // 锁定互斥量 std::cout Thread std::this_thread::get_id() entered recursive function at depth depth std::endl; if (depth 0) { recursive_function(depth - 1); // 递归调用再次锁定互斥量 } std::cout Thread std::this_thread::get_id() is leaving recursive function at depth depth std::endl; mtx.unlock(); // 解锁互斥量 } int main() { std::thread t1(recursive_function, 3); // 创建一个线程执行递归函数深度为3 t1.join(); // 等待线程完成 return 0; }上面代码的输出为 Thread 5968 entered recursive function at depth 3 Thread 5968 entered recursive function at depth 2 Thread 5968 entered recursive function at depth 1 Thread 5968 entered recursive function at depth 0 Thread 5968 is leaving recursive function at depth 0 Thread 5968 is leaving recursive function at depth 1 Thread 5968 is leaving recursive function at depth 2 Thread 5968 is leaving recursive function at depth 3这个示例创建了一个 std::recursive_mutex 对象 mtx并在 recursive_function 函数中多次调用 lock() 和 unlock()。由于 recursive_function 是一个递归函数它会多次尝试锁定同一个互斥量而不会导致死锁。如果这里使用的是 std::mutex 而不是 std::recursive_mutex那么程序将会出现未定义行为很可能是死锁。 6 std::call_once std::call_once 是 C 标准库中的一个非常有用的工具用于确保某个函数在多线程环境中只被调用一次。这在初始化资源或执行只需要运行一次的代码时非常有用。 工作原理 std::call_once 的工作原理基于一个 std::once_flag 对象。当调用 std::call_once 时它首先检查 std::once_flag 的状态。如果标志指示函数已经被调用过那么 std::call_once 将立即返回而不执行任何操作。如果标志指示函数尚未被调用那么 std::call_once 将执行提供的函数并在执行完成后设置标志以防止该函数再次被调用。 函数原型 函数原型如下 templateclass Callable, class... Args void call_once(std::once_flag flag, Callable f, Args... args);std::once_flag flag这是一个引用到 std::once_flag 对象的参数用于跟踪函数是否已经被调用过。Callable f这是要调用的函数或可调用对象。Args… args这是传递给函数f的参数包。 注意事项 如果在调用 std::call_once 时std::once_flag 指示函数f已经调用过那么 std::call_once 将立即返回不会再次调用f。如果在调用函数 f 时抛出了异常那么这个异常将传播给 std::call_once 的调用方并且 std::once_flag 不会被改变状态即仍然表示函数尚未被成功调用。如果有多个线程同时尝试在 std::once_flag 未设置即函数未调用过时调用 std::call_once那么这些调用将被组成单独全序并依次执行。也就是说尽管有多个线程尝试调用但函数 f 本身只会被执行一次。 示例 下面是一个简单的示例展示了如何使用 std::call_once 来确保一个函数在多线程环境中只被调用一次 #include iostream #include thread #include mutex std::once_flag once_flag; // 全局的 once_flag 对象 void init() { std::call_once(once_flag, []() { std::cout Initialization function called once. std::endl; // 这里执行只需要执行一次的初始化代码 }); } void worker() { init(); // 调用 init 函数它将使用 call_once 来确保只初始化一次 // 其他工作代码... } int main() { std::thread threads[5]; // 创建5个线程 for (int i 0; i 5; i) { threads[i] std::thread(worker); // 每个线程都执行 worker 函数 } for (auto th : threads) { th.join(); // 等待所有线程完成 } return 0; }上面代码的输出为 Initialization function called once.这个示例创建了 5 个线程每个线程都调用 worker 函数。worker 函数又调用了 init 函数而 init 函数使用了 std::call_once 来确保初始化函数只被调用一次。尽管有 5 个线程同时运行但初始化函数只会被打印一次因为 std::call_once 确保了这一点。 7 std::mutex 的最佳实践 7.1 死锁的产生原因与影响 1死锁的产生原因 互斥死锁的首要条件是互斥即一个资源一次只能被一个线程或进程占用。如果多个线程争夺同一资源并且在获取资源时无法共享就可能导致死锁。占有且等待这是死锁的另一个条件它要求一个线程在等待其他线程释放资源的同时自己占有着至少一个资源。这样的情况下各线程之间就可能形成一个环路导致死锁。不可抢占不可抢占要求资源在被占用的情况下无法被强制抢占只能由占有者主动释放。如果一个线程占有资源后不愿意释放其他线程就可能因无法获得资源而陷入等待状态造成死锁。循环等待最后一个死锁产生的条件是循环等待即若干线程之间形成了一个循环每个线程都在等待下一个线程释放资源。这种循环等待会导致程序无法继续执行。 此外竞争不可抢占资源也是引起死锁的常见原因。通常系统中拥有的不可抢占资源数量不足以满足多个进程运行的需要使得进程在运行过程中会因争夺资源而陷入僵局如磁带机、打印机等。 进程推进顺序不当同样会引起死锁。进程在运行过程中请求和释放资源的顺序不当会导致死锁。信号量使用不当也会造成死锁。 2死锁的影响 资源浪费死锁导致系统中的资源被无效地占用而无法释放从而浪费了系统资源。程序停滞死锁会导致相关进程或线程被永久阻塞无法继续执行从而影响系统的正常运行。系统崩溃在一些情况下死锁可能导致系统崩溃从而造成严重的后果。 7.2 避免死锁的策略 以下是使用 std::mutex 避免死锁的一些关键策略 1避免嵌套锁 避免在一个线程中嵌套使用多个互斥锁因为这可能导致死锁特别是当锁的获取顺序在不同线程间不一致时。如果确实需要嵌套锁应确保所有线程都按照相同的顺序请求锁。 2锁定时限 使用 std::timed_mutex 或 std::recursive_timed_mutex 等带时限的互斥锁可以为锁操作设置超时时间。如果线程在指定的时间内未能获取到锁它可以选择放弃并处理相应的错误而不是无限期地等待下去这有助于减少死锁的可能性。 3锁的顺序 当多个线程需要访问多个共享资源时确保所有线程都以相同的顺序请求锁。这有助于防止循环等待条件的发生从而减少死锁的风险。 4避免持有锁执行长时间操作 尽量避免在持有锁的情况下执行长时间的操作或可能阻塞的操作因为这可能导致其他线程长时间等待锁从而增加死锁的风险。 5使用智能锁 使用 std::lock_guard 或 std::unique_lock 等智能锁可以确保锁在适当的时候被释放。这些智能锁在构造时自动获取锁在析构时自动释放锁从而减少了因忘记释放锁而导致的死锁风险。 6检测和恢复 实现死锁检测和恢复机制。这可以通过定期检查线程状态、监控锁的使用情况等方式来实现。当检测到死锁时可以采取一些措施来打破死锁如强制释放某些锁或终止某些线程。 7使用高级同步原语 考虑使用更高级的同步原语如 std::condition_variable、std::future 和 std::promise 等这些原语提供了更灵活的同步机制有时可以替代直接使用互斥锁从而减少死锁的风险。

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

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

相关文章

金融网站开发目的集团网站推广

来源:DeepTech深科技人脑中,数以千计的神经元间电信号交替传送不断,而长短不一的树突(神经元胞体延伸)在神经元信息整合中起到了关键作用,由此我们的大脑细胞才能正常反应运作。而这次,MIT 的神…

新建网站软件如何做网站免费搭桥链接

矩阵是线性代数课学习的重点内容之一,也是线性代数常见工具之一,在应用数学、统计分析、计算机科学、计算机图像处理级物理等多学科中均有应用。矩阵主要是指数据的行列排列的形式,由行row与列col所组成,在数学中M*N矩阵是指具有M…

太原建站模板源码阳江市网络问政平台登录

编辑 | 萝卜皮格拉斯哥大学(University of Glasgow)的研究人员提出了一种自主化学合成机器人,用于探索、发现和优化由实时光谱反馈、理论和机器学习算法驱动的纳米结构,这些算法控制反应条件并允许选择性地模板化反应。这种方法允…

企业网站建设服务内容瑞安营销网站建设

文章目录1. 比赛结果2. 题目1. LeetCode 5420. 商品折扣后的最终价格 easy2. LeetCode 5422. 子矩形查询 medium3. LeetCode 5423. 找两个和为目标值且不重叠的子数组 medium4. LeetCode 5421. 安排邮筒 hard1. 比赛结果 两题选手😂,前两题很水&#xf…

上海哪家网站建设公司好网站域名是什么

Array.prototype.forEach MDN解释forEach()方法是对数组的每个元素执行一个给定的函数,换句话来说就是在调用forEach()方法的时候,需要传入一个回调函数callback,循环每个数组内部元素时都会执行一次传入的回调函数callback forEach()方法的…

门户网站建设的企业79招商创业网

2024 7/7 转眼间就到周日啦!昨天下午开组会,开了三个半小时。如坐针毡,会后跑了个步、洗了个澡、洗了衣服、躺床上看了会《罪与罚》,睡着了。早上起来,去拿我昨晚充电的车,当我看到车没有停在昨天的位置&am…

如何建立电子商务网站网站开发设计文档

//官方的例子在质量上是有保证的,而各种教程和文档又局限于个人阅读和理解力。 进入jdk官网---找download,,,下滑鼠标----找到如: JDK 8 Demos and Samples 点击下载,,解压进入,比如…

0716网站建设前端开发课程

一、什么是IP代理与SK5代理? IP代理: IP代理是一种允许用户通过代理服务器进行网络连接的技术。用户请求经由代理服务器中转,从而实现隐藏真实IP地址,保护用户隐私,并在一定程度上突破IP访问限制。常见的IP代理有HTTP…

智能建站平台z江苏营销型网站策划

我有罪,直到现在才写集成测试(至少针对数据库相关事务)。 因此,为了消除内感,我阅读了如何在周末以最少的努力实现这一目标。 提供了一个小示例,描述了如何使用Spring和Hibernate轻松实现这一目标。 通过集…

珠海网站设计wordpress hestia

子查询: where字句的子查询: 通常用in关键字: 举个例子: in关键字: not in 关键字: in 也可以用于枚举集合: where中可以用子查询来作为集合来筛选元祖。 some,all的运算符号…

做网站商城如何优化多张图片排版设计欣赏

题目描述 Description小浣熊松松和朋友到野外露营,没想到遇上了π年一次的大洪水,好在松松是一只爱观察的小浣熊,他发现露营地的地形和洪水有如下性质: ①露营地可以被看做是一个N*M的矩形方阵,其中左上角坐标为…

部门规划书 网站建设如何做网站的自由撰稿人

我们可以用电感和电容的特性,以及电压和电流之间的不同步原理来解释PFC(功率因数校正)和LLC(谐振变换器)。 电感和电容的基本概念 电感(Inductor): 电感是一种储存电能的组件。它的电流变化比较慢,电流在电感中延迟,而电压变化得比较快。可以把电感想象成一个“滞后…

电商网站建设模板室内效果图用什么软件做最好

😀前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【五】,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章…

保定网站排名优化wordpress 文章的标签

重新启动企业应用程序时,客户打开Web浏览器时会看到什么? 他们什么也没看到,服务器还没有响应,因此Web浏览器显示ERR_CONNECTION_REFUSED 应用程序前面的Web代理(如果有)注意到它已关闭并显示“友好”错误…

阿里巴巴网站网络营销的平台做设计常用网站

目录 1. OSI/RM参考模型1.1. 物理层1.2. 数据链路层1.3. 网络层1.4. 传输层1.5. 会话层1.6. 表示层1.7. 应用层 2. TCP/IP参考模型3. 理解OSI七层模型 网络体系结构是线代网络技术的整体蓝图。 1. OSI/RM参考模型 开放互联参考模型(Open System Interconnection/…

开发高端网站建设北京网站开发网站建设

题库来源:安全生产模拟考试一点通公众号小程序 2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题是由安全生产模拟考试一点通提供,危险化学品生产单位安全生产管理人员证模拟考试题库是根据危…

香河住房与建设局网站网站没有备案是假的吗

malloc() 分配的是虚拟内存。 如果分配后的虚拟内存没有被访问的话,虚拟内存是不会映射到物理内存的,这样就不会占用物理内存了。 只有在访问已分配的虚拟地址空间的时候,操作系统通过查找页表,发现虚拟内存对应的页没有在物理内…

网站排名总是不稳定创建一个网站所需的成本

常用Java开发规范整理 命名时 接口类中的方法和属性不要加任何修饰符号( public 也不要加),保持代码的简洁性,并加上有效的 javadoc 注释代码中相同意义的概念的单词可能有多种,在业务中应该统一禁止中英文混合使用 …

成都 视频网站建设绍兴seo计费管理

在visionOS中,用户可以使用窗口来呈现2D或3D内容,或者使用体积来呈现3D内容和对象。Unity 将这些窗口中的应用程序描述为“窗口应用程序”。 默认情况下,如果您构建针对visionOS 平台的Unity 应用程序而未通过XR 插件管理器启用PolySpatial …

做暖暖XO网站上海环球金融中心简介

一 引言 本文章内容 授人以鱼不如授人以渔 时代在变,技术在不断的更新,如何让自己不会落伍 利用人工智能AI 帮助你不断的去成长。注意我说的是成长不是学习。在成年人的社会中只有成长,在不断的成长的过程中去学习。 天工AI 能解决你的太多数技术上的问题。 如何去学习一门技…