Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Masalah penyegerakan berbilang benang dan penyelesaian dalam C++

Masalah penyegerakan berbilang benang dan penyelesaian dalam C++

WBOY
WBOYasal
2023-10-09 17:32:101343semak imbas

Masalah penyegerakan berbilang benang dan penyelesaian dalam C++

Masalah dan penyelesaian penyegerakan berbilang benang dalam C++

Pengaturcaraan berbilang benang ialah satu cara untuk meningkatkan prestasi dan kecekapan program, tetapi ia juga membawa satu siri masalah penyegerakan. Dalam pengaturcaraan berbilang benang, berbilang benang boleh mengakses dan mengubah suai sumber data yang dikongsi pada masa yang sama, yang boleh membawa kepada keadaan perlumbaan data, kebuntuan, kelaparan dan masalah lain. Untuk mengelakkan masalah ini, kita perlu menggunakan mekanisme penyegerakan untuk memastikan kerjasama dan akses yang saling eksklusif antara rangkaian.

Dalam C++, kami boleh menggunakan pelbagai mekanisme penyegerakan untuk menyelesaikan masalah penyegerakan antara benang, termasuk kunci mutex, pembolehubah keadaan dan operasi atom. Di bawah kita akan membincangkan masalah penyegerakan biasa dan memberikan penyelesaian yang sepadan serta contoh kod.

1. Syarat pertandingan
Syarat pertandingan merujuk kepada berbilang rangkaian yang mengakses sumber yang dikongsi pada masa yang sama Disebabkan oleh ketidakpastian urutan akses, hasil pelaksanaan program tidak pasti. Untuk mengelakkan keadaan perlumbaan, kita perlu menggunakan kunci mutex untuk melindungi sumber yang dikongsi dan memastikan bahawa hanya satu utas boleh mengakses dan mengubah suai sumber yang dikongsi.

Berikut ialah contoh kod menggunakan kunci mutex untuk menyelesaikan masalah keadaan perlumbaan:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    counter++;
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Counter: " << counter << std::endl;

    return 0;
}

Dalam kod di atas, kami menggunakan std::mutex untuk mencipta kunci mutex mtx, dan kemudian gunakan std::lock_guard untuk mengunci mutex bagi memastikan hanya satu utas boleh melakukan operasi pembilang++. Ini memastikan bahawa hasil pembilang ditakrifkan dengan betul.

2. Kebuntuan
Kebuntuan bermakna dua atau lebih utas sedang menunggu antara satu sama lain untuk melepaskan sumber, menyebabkan program tidak dapat meneruskan pelaksanaan. Untuk mengelakkan kebuntuan, kita boleh menggunakan teknologi RAII (pemerolehan sumber adalah permulaan) dan mengelakkan menunggu berbilang kunci dan kaedah lain.

Berikut adalah contoh untuk mengelakkan kebuntuan:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx1, mtx2;

void thread1() {
    std::unique_lock<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 延迟10毫秒,让线程2有足够时间锁住mtx2
    std::unique_lock<std::mutex> lock2(mtx2);
    
    // 访问共享资源
    std::cout << "Thread 1" << std::endl;
}

void thread2() {
    std::unique_lock<std::mutex> lock2(mtx2);
    std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 延迟10毫秒,让线程1有足够时间锁住mtx1
    std::unique_lock<std::mutex> lock1(mtx1);
    
    // 访问共享资源
    std::cout << "Thread 2" << std::endl;
}

int main() {
    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();

    return 0;
}

Dalam kod di atas, kami menggunakan std::unique_lock<:mutex> dan bukannya std::lock_guard<:mutex>, supaya kunci boleh dikawal secara manual Dapatkan dan lepaskan. Kebuntuan dielakkan dengan mengunci satu mutex dan kemudian satu lagi dalam setiap benang.

3. Lapar
Lapar merujuk kepada situasi di mana benang tidak dapat memperoleh sumber yang diperlukan atas sebab tertentu dan tidak dapat meneruskan pelaksanaan. Untuk mengelakkan kebuluran, kita boleh menggunakan keutamaan kunci, penjadualan adil dan mekanisme lain untuk memastikan benang memperoleh sumber secara adil.

Berikut ialah contoh kod yang menggunakan keutamaan kunci mutex untuk menyelesaikan masalah kebuluran:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
    while (true) {
        lock.lock(); // 获取互斥锁
        counter++;
        lock.unlock(); // 释放互斥锁
    }
}

void decrement() {
    std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
    while (true) {
        lock.lock(); // 获取互斥锁
        counter--;
        lock.unlock(); // 释放互斥锁
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(decrement);

    t1.join();
    t2.join();

    return 0;
}

Dalam kod di atas, kami menggunakan parameter std::defer_lock untuk menangguhkan pemerolehan kunci mutex, dan kemudian panggil ia secara manual apabila diperlukan lock.lock() untuk mendapatkan kunci mutex. Ini memastikan bahawa benang memperoleh mutex secara adil dan mengelakkan masalah kebuluran.

Ringkasan:
Masalah penyegerakan berbilang benang merupakan salah satu cabaran penting dalam pengaturcaraan berbilang benang Pemilihan dan penggunaan mekanisme penyegerakan yang munasabah adalah kunci untuk menyelesaikan masalah ini. Dalam C++, kita boleh menggunakan kunci mutex, pembolehubah keadaan dan operasi atom untuk mencapai penyegerakan dan kerjasama antara benang. Dengan mereka bentuk dan menulis program berbilang benang dengan betul, kami boleh menyelesaikan masalah penyegerakan berbilang benang dengan berkesan dan meningkatkan prestasi dan kebolehpercayaan program.

Atas ialah kandungan terperinci Masalah penyegerakan berbilang benang dan penyelesaian dalam C++. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn