ถึงแม้ว่าผมเองจะเขียน C++ มาตั้งแต่ตอนเรียนปี 1 แต่หลายๆ ครั้งก็ยังสับสนเรื่องชนิดของตัวแปรอยู่ดี หลังจากปี 1 ก็เขียนมาหลายภาษา ไม่ว่าจะเป็น JAVA PHP Python ยิ่งส่งผลให้สับสนเรื่องลักษณะเด่นของแต่ละภาษา มาวันนี้เริ่มลองเขียน thread ใน C++0x ก็เจอดีอีกจนได้ เนื่องจาก object ใน C/C++ เป็น strong type ไม่เหมือนใน JAVA ที่เป็น reference พอเขียนให้เธรดทำงานจากนั้นไปเปลี่ยนแปลงสมาชิกข้อมูลของ class แต่ object ที่รันอยู่โดย std::thread กลับไม่เปลี่ยนแปลงอะไรเลย โจทย์คือทำอย่างไรให้ object มันใช้ข้อมูลร่วมกันได้ หาไปหามาปรากฎว่าเป็นเพราะไม่ยอมอ่าน doc นี่เอง !!_ _ Multi-threading in C++0x ได้แสดงตัวอย่างการใช้งานไว้ค่อนข้างละเอียดทีเดียว เลยลองมาเขียนเองเล่นๆ ดังตัวอย่างด้านล่าง
เมื่อคอมไพล์แล้วรันจะได้ผลดังนี้
หากพิจารณา dw2 เป็นการส่งผ่านโดยใช้คำสงวน std::ref ไปให้ constractor ของ std::thread t2 จะให้ค่าที่ต่างกันออกไป เนื่องจากอ็อบเจกต์ dw2 ที่ทำงานใน t2 เป็นอ็อบเจกต์เดียวกัน สังเกตได้จาก address ของ this pointer มีค่าเดียวกันคือ 0x7fff876d183f ดังนั้นสามารถกำหนดค่าให้ dw2 ที่รันอยู่ใน t2 ได้ทันที แต่แค่นี้ก็เล่นเอาหอบ :D
#include <iostream>
#include <thread>
using namespace std;
class DoWork
{
public:
DoWork(){
cout << "this in constructor : " << this << endl;
this->running = false;
}
bool running;
void operator()(){
cout << "show running by operator : " << running << endl;
cout << "show this by operator : " << this << endl;
sleep(2);
cout << "show running by operator after wake up : "<< running << endl;
}
void showRunning(){
cout << "show running : " << running << endl;
cout << "show this in show : " << this << endl;
}
};
int main(){
//pass dw to thread by value
cout << "pass dw1 to thread" << endl;
DoWork dw1;
dw1.showRunning();
thread t1(dw1);
sleep(1);
dw1.running = true;
dw1.showRunning();
sleep(1);
t1.join();
//pass dw to thread by reference
cout << endl << "pass dw2 to thread" << endl;
DoWork dw2;
dw2.showRunning();
thread t2(std::ref(dw2));
sleep(1);
dw2.running = true;
dw2.showRunning();
t2.join();
return 0;
}
เมื่อคอมไพล์แล้วรันจะได้ผลดังนี้
$ g++ thread_val.cpp --std=c++0x -lpthread $ ./a.out pass dw1 to thread this in constructor : 0x7fff876d184f show running : 0 show this in show : 0x7fff876d184f show running by operator : 0 show this by operator : 0x1a55048 show running : 1 show this in show : 0x7fff876d184f show running by operator after wake up : 0 pass dw2 to thread this in constructor : 0x7fff876d183f show running : 0 show this in show : 0x7fff876d183f show running by operator : 0 show this by operator : 0x7fff876d183f show running : 1 show this in show : 0x7fff876d183f show running by operator after wake up : 1เมื่อทดสอบรันดูจะได้ผลดังที่แสดงไว้ ในตัวอย่างแรก dw1 นั้นผมส่งอ็อบเจกต์ไปให้ contractor ของ std::thread เลย โดยปรกติตัวแปล running จะมีค่าเป็น false แล้วพยายามกำหนดค่าให้ตัวแปล running ซึ่งเป็นสมาชิกของ DoWork เป็น true ผลที่ได้คือตัวแปร running ใน dw1 เป็น true จริง แต่เป็นคนละอ็อบเจกต์กันที่ทำงานอยู่ในเธรด t1 หากสังเกตดูจะพบว่า this pointer จะมี address ต่างกันคือ dw1 ที่อยู่ใน main จะมีค่าเป็น 0x7fff876d184f ส่วนใน t1 จะมีค่าเป็น 0x1a55048 ซึ่งเป็นคนละตำแหน่งกัน
หากพิจารณา dw2 เป็นการส่งผ่านโดยใช้คำสงวน std::ref ไปให้ constractor ของ std::thread t2 จะให้ค่าที่ต่างกันออกไป เนื่องจากอ็อบเจกต์ dw2 ที่ทำงานใน t2 เป็นอ็อบเจกต์เดียวกัน สังเกตได้จาก address ของ this pointer มีค่าเดียวกันคือ 0x7fff876d183f ดังนั้นสามารถกำหนดค่าให้ dw2 ที่รันอยู่ใน t2 ได้ทันที แต่แค่นี้ก็เล่นเอาหอบ :D
ความคิดเห็น
แสดงความคิดเห็น