Yazılım Geliştirme: Değişikliği Yönetme – Tutulan Süspansiyon
Modern yazılımın geliştirilmesinde önemli bir soyutlama olarak, modeller açıkça tanımlanmış terminoloji, temiz belgeler ve en iyi öğrenme sunar. Bu makale rekabet modellerini yönetmeye devam etmektedir. Korunan süspansiyon, değişimle yüzleşmek için özel bir strateji kullanır. Değişikliği ile sonuçlandığında rapor.
Korunan süspansiyonun temel varyantı, bir bloğu tatmin edilmesi gereken bir ön ile birleştirir. Önkoşul tatmin değilse, test ipliği uyur. Kontrol iş parçacığı, bir veri yarışına veya çıkmaza yol açabilecek bir yarış koşulundan kaçınmak için bir blok kullanır.
Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
Tutulan süspansiyonun farklı varyantları vardır:
Çekmeye karşı itme ilkesi
İtme prensibi ile başlamak istiyorum.
İtme prensibi
Koşulların değişkenleri veya gelecekteki bir çift/ünlü genellikle iş parçacıklarını senkronize etmek için kullanılır. Durumun durumu veya sözün, bildirimi iş parçacığı beklemesine gönderir. Bir sözün kimse yok notify_one- VEYA notify_all-Üyenin işlevi. Genellikle işe yaramaz bir değer set_value-Call bir bildirim bildirirdi. Programın aşağıdaki bölümleri, bildirimi ve iş parçacığını bekleyen iş parçacığını gösterir.
void waitingForWork(){
std::cout << "Worker: Waiting for work." << 'n';
std::unique_lock<std::mutex> lck(mutex_);
condVar.wait(lck, []{ return dataReady; });
doTheWork();
std::cout << "Work done." << 'n';
}
void setDataReady(){
{
std::lock_guard<std::mutex> lck(mutex_);
dataReady = true;
}
std::cout << "Sender: Data is ready." << 'n';
condVar.notify_one();
}
void waitingForWork(std::future<void>&& fut){
std::cout << "Worker: Waiting for work." << std::endl;
fut.wait();
doTheWork();
std::cout << "Work done." << std::endl;
}
void setDataReady(std:
romise<void>&& prom){
std::cout << "Sender: Data is ready." << std::endl;
prom.set_value();
}
Prensibi Çıkarın
Geliştiriciler, devlet değişikliği için pasif yerine de aktif olarak talep edebilirler. Bu çekme prensibi C ++ desteklemez, ancak örneğin atomik veri türleriyle uygulanabilir.
std::vector<int> mySharedWork;
std::atomic<bool> dataReady(false);
void waitingForWork(){
std::cout << "Waiting " << 'n';
while (!dataReady.load()){
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
mySharedWork[1] = 2;
std::cout << "Work done " << 'n';
}
void setDataReady(){
mySharedWork = {1, 0, 3};
dataReady = true;
std::cout << "Data prepared" << 'n';
}
Zaman sınırları ile ve zaman sınırları olmadan bekleyin
Durum durumu ve bir geleceğin beklemek için üç üyesi vardır: wait, wait_for VE wait_until. . wait_for-Adery bir süre gerektirir ve wait_until-zaman içinde. Çeşitli bekleme stratejilerinde, tüketici dizisi, zaman boyunca aşağıdaki kod örneğinde bekliyor steady_clock::now() + dur. Gelecek değer ister; Söz henüz bitmezse, gelecek sadece kimliğini gösterir:
void producer(promise<int>&& prom){
cout << "PRODUCING THE VALUE 2011nn";
this_thread::sleep_for(seconds(5));
prom.set_value(2011);
}
void consumer(shared_future<int> fut,
steady_clock::duration dur){
const auto start = steady_clock::now();
future_status status= fut.wait_until(steady_clock::now() + dur);
if ( status == future_status::ready ){
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " ready => Result: " << fut.get()
<< 'n';
}
else{
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " stopped waiting." << 'n';
}
const auto end= steady_clock::now();
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " waiting time: "
<< getDifference(start,end) << " ms" << 'n';
}
Bekleyen iş parçacığını veya tamamını bilgilendirin
notify_one Beklenen tellerden biri, notify_all Bekleyen tüm iplikleri uyandırır. İle notify_one Özellikle hangi ipliğin uyandığı belirlenemez. Açılmamış iplik bekleme durumunda kalır. İle std::future Olamaz çünkü gelecek ve vaat arasında bireysel bir ilişki vardır. Bireysel bir ilişki varsa, std::shared_future Yerine std::future Kopyalanabilir çünkü kullanılabilir.
Aşağıdaki program, bireysel bir ilişkiye sahip basit bir iş akışı ve vaatler ile gelecek arasında birer birer bir iş akışı göstermektedir.
// bossWorker.cpp
#include <future>
#include <chrono>
#include <iostream>
#include <random>
#include <string>
#include <thread>
#include <utility>
int getRandomTime(int start, int end){
std::random_device seed;
std::mt19937 engine(seed());
std::uniform_int_distribution<int> dist(start,end);
return dist(engine);
};
class Worker{
public:
explicit Worker(const std::string& n):name
{};
void operator() (std:
romise<void>&& preparedWork,
std::shared_future<void> boss2Worker){
// prepare the work and notfiy the boss
int prepareTime= getRandomTime(500, 2000);
std::this_thread::sleep_for(std::chrono::milliseconds(prepareTime));
preparedWork.set_value(); // (5)
std::cout << name << ": " << "Work prepared after "
<< prepareTime << " milliseconds." << 'n';
// still waiting for the permission to start working
boss2Worker.wait();
}
private:
std::string name;
};
int main(){
std::cout << 'n';
// define the std:
romise => Instruction from the boss
std:
romise<void> startWorkPromise;
// get the std::shared_future's from the std:
romise
std::shared_future<void> startWorkFuture= startWorkPromise.get_future();
std:
romise<void> herbPrepared;
std::future<void> waitForHerb = herbPrepared.get_future();
Worker herb(" Herb"); // (1)
std::thread herbWork(herb, std::move(herbPrepared), startWorkFuture);
std:
romise<void> scottPrepared;
std::future<void> waitForScott = scottPrepared.get_future();
Worker scott(" Scott"); // (2)
std::thread scottWork(scott, std::move(scottPrepared), startWorkFuture);
std:
romise<void> bjarnePrepared;
std::future<void> waitForBjarne = bjarnePrepared.get_future();
Worker bjarne(" Bjarne"); // (3)
std::thread bjarneWork(bjarne, std::move(bjarnePrepared), startWorkFuture);
std::cout << "BOSS: PREPARE YOUR WORK.n " << 'n';
// waiting for the worker
waitForHerb.wait(), waitForScott.wait(), waitForBjarne.wait(); // (4)
// notify the workers that they should begin to work
std::cout << "nBOSS: START YOUR WORK. n" << 'n';
startWorkPromise.set_value(); // (6)
herbWork.join();
scottWork.join();
bjarneWork.join();
}
Programın ana fikri, başın (ana iş) üç işçisi olmasıdır: herb (Satır 1), scott (Satır 3) e bjarne (Satır 3). Her işçi bir iş parçacığı ile temsil edilir. (4) 'de, tüm işçiler çalışma paketlerini hazırlayana kadar patron bekliyor. Bu, her işçinin herhangi bir zamanda başını patrona gönderdiği anlamına gelir. İşçinin patrona bildirimi bireysel bir ilişkidir çünkü std::future kullanılır (satır 5). Aksine, işle başlama eğitimi, birinden genişliğe (6. satır) işçilerine kadar bir ilişkidir. Bu bire çok bildirim için std::shared_future gerekli.
Küçük bir yaz tatili
Önümüzdeki iki hafta içinde kısa bir yaz tatili yapacağım ve blogda bir makale yayınlamayacağım. Bir sonraki makalem 19 Haziran'da yayınlanacak.
Temiz Kod Eğitimi
(harita)
Yazılım Geliştirme: Değişikliği Yönetme – Tutulan Süspansiyon
Modern yazılımın geliştirilmesinde önemli bir soyutlama olarak, modeller açıkça tanımlanmış terminoloji, temiz belgeler ve en iyi öğrenme sunar. Bu makale rekabet modellerini yönetmeye devam etmektedir. Korunan süspansiyon, değişimle yüzleşmek için özel bir strateji kullanır. Değişikliği ile sonuçlandığında rapor.

Korunan süspansiyonun temel varyantı, bir bloğu tatmin edilmesi gereken bir ön ile birleştirir. Önkoşul tatmin değilse, test ipliği uyur. Kontrol iş parçacığı, bir veri yarışına veya çıkmaza yol açabilecek bir yarış koşulundan kaçınmak için bir blok kullanır.

Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
Tutulan süspansiyonun farklı varyantları vardır:
- Bekleyen iş parçacığı pasif olarak devlet değişikliğini bilgilendirebilir veya aktif olarak devlette değişiklik isteyebilir. Bu, Pull'a karşı itme prensibine karşılık gelir.
- Bekleme, zaman sınırı ile veya zaman sınırı olmadan gerçekleşebilir.
- Bildirim, bekleyen bir veya tüm iş parçacığına gönderilebilir.
Çekmeye karşı itme ilkesi
İtme prensibi ile başlamak istiyorum.
İtme prensibi
Koşulların değişkenleri veya gelecekteki bir çift/ünlü genellikle iş parçacıklarını senkronize etmek için kullanılır. Durumun durumu veya sözün, bildirimi iş parçacığı beklemesine gönderir. Bir sözün kimse yok notify_one- VEYA notify_all-Üyenin işlevi. Genellikle işe yaramaz bir değer set_value-Call bir bildirim bildirirdi. Programın aşağıdaki bölümleri, bildirimi ve iş parçacığını bekleyen iş parçacığını gösterir.
void waitingForWork(){
std::cout << "Worker: Waiting for work." << 'n';
std::unique_lock<std::mutex> lck(mutex_);
condVar.wait(lck, []{ return dataReady; });
doTheWork();
std::cout << "Work done." << 'n';
}
void setDataReady(){
{
std::lock_guard<std::mutex> lck(mutex_);
dataReady = true;
}
std::cout << "Sender: Data is ready." << 'n';
condVar.notify_one();
}
void waitingForWork(std::future<void>&& fut){
std::cout << "Worker: Waiting for work." << std::endl;
fut.wait();
doTheWork();
std::cout << "Work done." << std::endl;
}
void setDataReady(std:
std::cout << "Sender: Data is ready." << std::endl;
prom.set_value();
}
Prensibi Çıkarın
Geliştiriciler, devlet değişikliği için pasif yerine de aktif olarak talep edebilirler. Bu çekme prensibi C ++ desteklemez, ancak örneğin atomik veri türleriyle uygulanabilir.
std::vector<int> mySharedWork;
std::atomic<bool> dataReady(false);
void waitingForWork(){
std::cout << "Waiting " << 'n';
while (!dataReady.load()){
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
mySharedWork[1] = 2;
std::cout << "Work done " << 'n';
}
void setDataReady(){
mySharedWork = {1, 0, 3};
dataReady = true;
std::cout << "Data prepared" << 'n';
}
Zaman sınırları ile ve zaman sınırları olmadan bekleyin
Durum durumu ve bir geleceğin beklemek için üç üyesi vardır: wait, wait_for VE wait_until. . wait_for-Adery bir süre gerektirir ve wait_until-zaman içinde. Çeşitli bekleme stratejilerinde, tüketici dizisi, zaman boyunca aşağıdaki kod örneğinde bekliyor steady_clock::now() + dur. Gelecek değer ister; Söz henüz bitmezse, gelecek sadece kimliğini gösterir:
void producer(promise<int>&& prom){
cout << "PRODUCING THE VALUE 2011nn";
this_thread::sleep_for(seconds(5));
prom.set_value(2011);
}
void consumer(shared_future<int> fut,
steady_clock::duration dur){
const auto start = steady_clock::now();
future_status status= fut.wait_until(steady_clock::now() + dur);
if ( status == future_status::ready ){
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " ready => Result: " << fut.get()
<< 'n';
}
else{
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " stopped waiting." << 'n';
}
const auto end= steady_clock::now();
lock_guard<mutex> lockCout(coutMutex);
cout << this_thread::get_id() << " waiting time: "
<< getDifference(start,end) << " ms" << 'n';
}
Bekleyen iş parçacığını veya tamamını bilgilendirin
notify_one Beklenen tellerden biri, notify_all Bekleyen tüm iplikleri uyandırır. İle notify_one Özellikle hangi ipliğin uyandığı belirlenemez. Açılmamış iplik bekleme durumunda kalır. İle std::future Olamaz çünkü gelecek ve vaat arasında bireysel bir ilişki vardır. Bireysel bir ilişki varsa, std::shared_future Yerine std::future Kopyalanabilir çünkü kullanılabilir.
Aşağıdaki program, bireysel bir ilişkiye sahip basit bir iş akışı ve vaatler ile gelecek arasında birer birer bir iş akışı göstermektedir.
// bossWorker.cpp
#include <future>
#include <chrono>
#include <iostream>
#include <random>
#include <string>
#include <thread>
#include <utility>
int getRandomTime(int start, int end){
std::random_device seed;
std::mt19937 engine(seed());
std::uniform_int_distribution<int> dist(start,end);
return dist(engine);
};
class Worker{
public:
explicit Worker(const std::string& n):name
void operator() (std:
std::shared_future<void> boss2Worker){
// prepare the work and notfiy the boss
int prepareTime= getRandomTime(500, 2000);
std::this_thread::sleep_for(std::chrono::milliseconds(prepareTime));
preparedWork.set_value(); // (5)
std::cout << name << ": " << "Work prepared after "
<< prepareTime << " milliseconds." << 'n';
// still waiting for the permission to start working
boss2Worker.wait();
}
private:
std::string name;
};
int main(){
std::cout << 'n';
// define the std:
std:
// get the std::shared_future's from the std:
std::shared_future<void> startWorkFuture= startWorkPromise.get_future();
std:
std::future<void> waitForHerb = herbPrepared.get_future();
Worker herb(" Herb"); // (1)
std::thread herbWork(herb, std::move(herbPrepared), startWorkFuture);
std:
std::future<void> waitForScott = scottPrepared.get_future();
Worker scott(" Scott"); // (2)
std::thread scottWork(scott, std::move(scottPrepared), startWorkFuture);
std:
std::future<void> waitForBjarne = bjarnePrepared.get_future();
Worker bjarne(" Bjarne"); // (3)
std::thread bjarneWork(bjarne, std::move(bjarnePrepared), startWorkFuture);
std::cout << "BOSS: PREPARE YOUR WORK.n " << 'n';
// waiting for the worker
waitForHerb.wait(), waitForScott.wait(), waitForBjarne.wait(); // (4)
// notify the workers that they should begin to work
std::cout << "nBOSS: START YOUR WORK. n" << 'n';
startWorkPromise.set_value(); // (6)
herbWork.join();
scottWork.join();
bjarneWork.join();
}
Programın ana fikri, başın (ana iş) üç işçisi olmasıdır: herb (Satır 1), scott (Satır 3) e bjarne (Satır 3). Her işçi bir iş parçacığı ile temsil edilir. (4) 'de, tüm işçiler çalışma paketlerini hazırlayana kadar patron bekliyor. Bu, her işçinin herhangi bir zamanda başını patrona gönderdiği anlamına gelir. İşçinin patrona bildirimi bireysel bir ilişkidir çünkü std::future kullanılır (satır 5). Aksine, işle başlama eğitimi, birinden genişliğe (6. satır) işçilerine kadar bir ilişkidir. Bu bire çok bildirim için std::shared_future gerekli.

Küçük bir yaz tatili
Önümüzdeki iki hafta içinde kısa bir yaz tatili yapacağım ve blogda bir makale yayınlamayacağım. Bir sonraki makalem 19 Haziran'da yayınlanacak.
Temiz Kod Eğitimi
(harita)