A program is consist a one or more process!
Each process consist one or more thread!
Mỗi process có một tài nguyên và vùng nhớ xác định! Các thread trong cùng một process thì cùng nhau chia sẻ tài nguyên của process!
When working with thread maybe it gona defference between OS (Windows and Unix-Linux)!
Do thread working with the same memory so in case of multi thread thì sinh ra việc phải đồng bộ hóa (synchronize) các thread với nhau để tránh trường hợp đọc và ghi không đồng nhất vào trên 1 vùng nhớ (ví dụ như 1 biến hoặc 1 object nào đó!)
Ví dụ về multithread
/* Add this to .pro file QMAKE_CXXFLAGS += -std=c++0x -pthread LIBS += -pthread */ using namespace std; void printJob(char c, int count) { for (int i = 0; i < count; ++i) { cout << c; } } int main() { std::thread printStar (printJob, '*', 100); std::thread printDola (printJob, '$', 100); printDola.join(); printStar.join(); return 0; }A: Do test quá nhỏ nên trên Ubuntu có thể không thấy, cứ cho test thật lớn vào thì sẽ xảy ra bất đồng bộ!
Một trong những kỹ thuật người ta hay sử dụng để đồng bộ hóa các thread là sử dụng mutex, mutex đã được hỗ trợ sẵn trên C++11!
Chỉ cần thêm một đoạn lock và unlock sử dụng biến mutex là có thể đồng bộ hóa được rồi
mutex locker; void printJob(char c, int count) { locker.lock(); for (int i = 0; i < count; ++i) { cout << c; } locker.unlock(); }
Ở đây ta gọi phần bao quanh bởi biến locker kia là Critical Section, đó là đoạn code mà chỉ cho phép tại 1 thời điểm chỉ cho phép 1 thread thực thi đoạn code đó! (Mục đích là ta muốn các ký tự in ra liên tục theo đúng thứ tự!)
Mutex là viết tắt của “Mutual Exclusion” là việc giải quyết trùng lặp!
Một trong các ví dụ phổ biến trong multithread là producer-consumer problem! Problem như sau: Một thread chuyên sản xuất, một thread chuyên tiêu thụ, tránh conflic khi mà sản phẩm đã hết mà khách hàng vẫn tiêu thụ!
/* Add this to .pro file QMAKE_CXXFLAGS += -std=c++0x -pthread LIBS += -pthread */ using namespace std; int productCount = 0; void producerProc() { while(true) { productCount += (1 + rand()%10); cout << "Producer produce " << productCount << endl; this_thread::sleep_for(chrono::milliseconds(rand() % 2000)); } } void consumerProc() { while(true) { productCount -= (1 + rand()%10); cout << "Consumer consume " << productCount << endl; this_thread::sleep_for(chrono::milliseconds(rand() % 2000)); } } int main() { thread producerThread(producerProc); thread consumerThread(consumerProc); producerThread.join(); consumerThread.join(); return 0; }Như trên chưa làm gì để đồng bộ thì sẽ có trường hợp cusumer thực hiện việc trừ thành âm (<0) số product!
Như vậy việc giải quyết đồng bộ ở đây như thế nào?
Ta có thể nghĩ đến việc sử dụng mutex rồi lock vào ntn:
void producerProc() { while(true) { locker.lock(); productCount += (1 + rand()%10); cout << "Producer produce " << productCount << endl; this_thread::sleep_for(chrono::milliseconds(rand() % 2000)); locker.unlock(); } } void consumerProc() { while(true) { locker.lock(); productCount -= (1 + rand()%10); cout << "Consumer consume " << productCount << endl; this_thread::sleep_for(chrono::milliseconds(rand() % 2000)); locker.unlock(); } }Như này thì các lệnh sẽ coi như là chạy lần lượt!
Ta có thể thấy sự khác nhau nếu như ta unlock biến mutex ở trước vào sau khi sleep!
/* Add this to .pro file QMAKE_CXXFLAGS += -std=c++0x -pthread LIBS += -pthread */ using namespace std; mutex mtx; int productCount = 0; void producerProc(string name) { while(true) { mtx.lock(); int k = (1 + rand()%100); productCount += k; cout << "++++++++++++ " << name << " + " << k << " : " << productCount << endl; mtx.unlock(); this_thread::sleep_for(chrono::milliseconds(100 + rand() % 100)); } } void consumerProc(string name) { while(true) { int take = (1 + rand()%100); mtx.lock(); if(take <= productCount) { productCount -= take; cout << name << " consume -" << take <<" : " << productCount << endl; }else{ cout << name << " can't take " << take << "!" << endl; } mtx.unlock(); this_thread::sleep_for(chrono::milliseconds(rand() % 100)); } } int main() { srand(time(NULL)); thread producerThread1(producerProc, "P1"); thread producerThread2(producerProc, "P2"); thread consumerThread1(consumerProc, "A"); thread consumerThread2(consumerProc, "B"); producerThread1.join(); producerThread2.join(); consumerThread1.join(); consumerThread2.join(); return 0; }ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms681917(v=vs.85).aspx http://www.bogotobogo.com/cplusplus/multithreading_pthread.php
https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem http://108.61.119.12/multithreading-semaphores/ http://108.61.119.12/multithreading-producer-consumer-problem/
Related