Multi thread:mutex and varible
- No lock for two threads
- Atomic
- Mutex
-
- Mutex: Protect global variable only lock
- Mutex: Protect global variable with lock and unblock
- std::mutex::try_lock
- Conditional variable
-
- Print 1-100 with multi-thread
- Print 100 times "ABCABC" with three-thread
No lock for two threads
#include
#include
#include
using namespace std;
int gu_num=0;
void print(int id){
for (int i=0;i<5;i++){
++gu_num;
cout <<"id = " << id << " ==> " << gu_num << endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
g++ -o mutex mutex.cpp -lpthread
./mutex
id = id = 01 ==> ==> 22
id = id = 1 ==> 40 ==> 4
id = 1 ==> 5
id = 0 ==> 6
id = 1 ==> 8
id = 0 ==> 8
id = 1 ==> 9
id = 0 ==> 10
Atomic
#include
#include
#include
#include
using namespace std;
atomic_int gu_num (0);
void print(int id){
for (int i=0;i<5;i++){
++gu_num;
cout <<"id = " << id << " ==> " << gu_num << endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
./mutex
id = 0 ==> 2id =
1 ==> 2
id = 1 ==> 3
id = 0 ==> 4
id = 1 ==> 5
id = 0 ==> 6
id = 0 ==> 8
id = 1 ==> 8
id = 0 ==> 9
id = 1 ==> 10
Mutex
Mutex: Protect global variable only lock
#include
#include
#include
#include
#include
using namespace std;
int gu_num=0;
std::mutex mtx;
void print(int id){
for (int i=0;i<5;i++){
mtx.lock();
++gu_num;
cout <<"id = " << id << " ==> " << gu_num << endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
./mutex
id = 0 ==> 1
Mutex: Protect global variable with lock and unblock
#include
#include
#include
#include
#include
using namespace std;
int gu_num=0;
std::mutex mtx;
void print(int id){
for (int i=0;i<5;i++){
mtx.lock();
++gu_num;
cout <<"id = " << id << " ==> " << gu_num << endl;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
./mutex
id = 0 ==> 1
id = 1 ==> 2
id = 0 ==> 3
id = 1 ==> 4
id = 0 ==> 5
id = 1 ==> 6
id = 1 ==> 7
id = 0 ==> 8
id = 1 ==> 9
id = 0 ==> 10
std::mutex::try_lock
try_lock success: return true
try_lock fail: return false
Wrong example
#include
#include
#include
#include
#include
using namespace std;
int gu_num=0;
std::mutex mtx;
void print(int id){
int result=1;
for (int i=0;i<5;i++){
mtx.try_lock();
result = mtx.try_lock();
++gu_num;
cout << "try_lock result: " << result << "id = " << id << " ==> " << gu_num << endl;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
./mutex
try_lock result: 0id = 0 ==> 2try_lock result:
0id = 1 ==> 2
try_lock result: try_lock result: 0id = 0id = 1 ==> 40 ==> 4
try_lock result: 0id = 1 ==> 5
try_lock result: 0id = 0 ==> 6
try_lock result: 0id = 1 ==> 7
try_lock result: 0id = 0 ==> 8
try_lock result: 0id = 1 ==> 9
try_lock result: 0id = 0 ==> 10
Rright example
#include
#include
#include
#include
#include
using namespace std;
int gu_num=0;
std::mutex mtx;
void print(int id){
for (int i=0;i<5;i++){
while(!mtx.try_lock()){
cout << " failed " << endl;
}
++gu_num;
cout << "Success: id = " << id << " ==> " << gu_num << endl;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::microseconds(200));
}
}
int main(){
thread t1(print, 0);
thread t2(print, 1);
t1.join();
t2.join();
return 0;
}
Output:
./mutex
Success: id = 0 ==> 1
failed
Success: id = 1 ==> 2
Success: id = 0 ==> 3
Success: id = 1 ==> 4
Success: id = 0 ==> 5
Success: id = 1 ==> 6
Success: id = 0 ==> 7
Success: id = 1 ==> 8
Success: id = 0 ==> 9
Success: id = 1 ==> 10
Conditional variable
- Notify the blocked thread that the global variable value changed
notify_all,notify_all
- Block a thread to be waited until this thread was notified
wait,wait_for
Print 1-100 with multi-thread
#include
#include
#include
#include
#include
#include
using namespace std;
int n=100;
int i =1 ;
void print(){
for(i=1;i<=n;i++){
cout << "Line" << i << ": "<< i <<endl;
}
}
int main(){
clock_t start,end;
start = clock();
thread t(print);
t.join();
end = clock();
cout << "Run : " << (end - start) << endl;
cout << "i= " << (i-1) <<endl;
return 0;
}
Output:
Line1: 1
Line2: 2
Line3: 3
Line4: 4
........
Line97: 97
Line98: 98
Line99: 99
Line100: 100
Run : 165
i= 100
Print 100 times “ABCABC” with three-thread
#include
#include
#include
#include
#include
#include
#include
using namespace std;
std::mutex mtx;
std::condition_variable cv;
int i=0;
int isReady = 0;
const int n = 100;
void printA(){
std::unique_lock<std::mutex> lck(mtx);
while(i<=n){
while(isReady !=0){
cv.wait(lck);
}
isReady=1;
if(i>=n){
cv.notify_all();
break;
}
++i;
cout << "threadA : " << i << endl ;
cv.notify_all();
}
cout << "threadA Finish!" << endl;
}
void printB(){
std::unique_lock<std::mutex> lck(mtx);
while(i<=n){
while(isReady !=1){
cv.wait(lck);
}
isReady=2;
if(i>=n){
cv.notify_all();
break;
}
++i;
cout << "threadB : " << i << endl ;
cv.notify_all();
}
cout << "threadB Finish!" << endl;
}
void printC(){
std::unique_lock<std::mutex> lck(mtx);
while(i<=n){
while(isReady !=2){
cv.wait(lck);
}
isReady=0;
if(i>=n){
cv.notify_all();
break;
}
++i;
cout << "threadC : " << i << endl ;
cv.notify_all();
}
cout << "threadC Finish!" << endl;
}
int main(){
clock_t start,end;
start = clock();
thread A(printA);
thread B(printB);
thread C(printC);
A.join();
B.join();
C.join();
end = clock();
cout << endl << "i= " << i << endl;
cout << "Run : " << (end - start) << endl;
return 0;
}
Output:
threadA : 1
threadB : 2
threadC : 3
threadA : 4
.......
threadA : 97
threadB : 98
threadC : 99
threadA : 100
threadB Finish!
threadC Finish!
threadA Finish!
i= 100
Run : 931
+-----------------------------------------+
| Three-thread print "ABC" until 100 |
+-----------------------------------------+
|
V
/-----------\ N
| i<100 |-------------+
\-----------/ |
| Y |
V |
+-------------+ |
| printA | |
+-------------+ |
| |
V |
N /-----------------------\ |
+---| Get printC notify |<--+ |
| \-----------------------/ | |
| | Y | |
| V | |
| +---------------+ | |
| | print "A" | | |
| +---------------+ | |
| | | |
| V | |
| +---------------+ | |
| | isReady=1 | | |
| +---------------+ | |
| | | |
| V | |
| +---------+ | |
| | ++i | | |
| +---------+ | |
| | | |
| V | |
| +-------------------+ | |
| | notify printB |-----+ |
| +-------------------+ |
| |
| |
| +-----------+ |
+-------->| wait | |
+-----------+ |
| |
V |
+-------------+ |
| printB | |
+-------------+ |
| |
V |
N /-----------------------\ |
+---| Get printA notify |<--+ |
| \-----------------------/ | |
| | Y | |
| V | |
| +---------------+ | |
| | print "B" | | |
| +---------------+ | |
| | | |
| V | |
| +---------------+ | |
| | isReady=2 | | |
| +---------------+ | |
| | | |
| V | |
| +---------+ | |
| | ++i | | |
| +---------+ | |
| | | |
| V | |
| +-------------------+ | |
| | notify printC |-----+ |
| +-------------------+ |
| |
| |
| +-----------+ |
+-------->| wait | |
+-----------+ |
| |
V |
+-------------+ |
| printC | |
+-------------+ |
| |
V |
N /-----------------------\ |
+---| Get printB notify |<--+ |
| \-----------------------/ | |
| | Y | |
| V | |
| +---------------+ | |
| | print "C" | | |
| +---------------+ | |
| | | |
| V | |
| +---------------+ | |
| | isReady=0 | | |
| +---------------+ | |
| | | |
| V | |
| +---------+ | |
| | ++i | | |
| +---------+ | |
| | | |
| V | |
| +-------------------+ | |
| | notify printA |-----+ |
| +-------------------+ |
| |
| |
| +-----------+ |
+-------->| wait | |
+-----------+ |
| |
V |
O<------------------+
#include
#include
#include
#include
#include
#include
#include
using namespace std;
std::mutex mtx;
std::condition_variable cv;
int i=1;
int isReady = 0;
const int n = 100;
void printA(){
std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lck(mtx);
while(i<n){
while(isReady !=0){
cv.wait(lck);
}
cout << "A " ;
isReady=1;
if(i>=n){
cv.notify_all();
break;
}
++i;
cv.notify_all();
}
}
void printB(){
std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lck(mtx);
while(i<n){
while(isReady !=1){
cv.wait(lck);
}
cout<<"B ";
isReady=2;
if(i>=n){
cv.notify_all();
break;
}
++i;
cv.notify_all();
}
}
void printC(){
std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lck(mtx);
while(i<n){
while(isReady !=2){
cv.wait(lck);
}
cout<<"C ";
isReady=0;
if(i>=n){
cv.notify_all();
break;
}
++i;
cv.notify_all();
}
}
int main(){
thread A(printA);
thread B(printB);
thread C(printC);
A.join();
B.join();
C.join();
cout << endl << "i= " << i << endl;
return 0;
}
Output:
A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C A B
i= 100