1、首先考虑,什么情况下使用多线程?
第一种情况:做事情A的过程中,顺便去做事情B,不需要B完成,可以接着做A余下的部分。这种情况下,对于事情B启动一个线程,往往需要传入一个回调方法,等事情B完成后,在主线程上执行回调方法。
第二种情况:事情A和事情B同时做,他们访问同一块数据,需要对这块数据加锁。
2、考虑下面的需求,两个线程t1,t2,修改同一个数据,t1每次增加1,t2每次减2,怎么做?
a、首先肯定要准备两个方法Add1和Sub2,分别传给t1,t2;
b、准备共享资源和互斥体mutex(也就是值为1 的信号量);
c、Add1和Sub2方法内分别加锁,在加锁的语句块内,修改共享资源。
3、上面的需求,只要求一个一个访问,并没有要求t1和t2之间进行一定的协作。考虑下面的需求,t1,t2轮流打印,t1打印1,t2打印2,t1打印3,t2打印4,。。。。该怎么办?
a、当然第一步,还是必须要准备两个方法,PrintOdd和PrintEven;
b、准备共享资源和互斥体mutex;
c、Add1和Sub2方法内分别加锁,在加锁的语句块内,修改共享资源。
特别注意的是:这种情况下,加锁成功后,修改共享资源之前,必须检查修改的前提条件是否满足。也就是说,按道理轮到自己了,但是还必须要检查前提条件是否满足,如果不满足,这次把锁释放,继续下一次申请加锁。
那么,这里就有问题了。加锁成功后,前提条件不满足,不能修改,并且要释放锁。有没有更好的办法呢?
先看前提条件是否满足,不满足,不去申请加锁,因为就算加锁成功,也不能修改,没意义。
如果前提条件满足的话,才去申请加锁。特别注意的是:在加锁的语句中,需要再次检查前提条件,为什么?考虑这种极端情况,条件满足,去申请加锁,在申请加锁,到加锁成功这段时间内,假如其他线程修改了共享资源,可能导致前提条件又不满足了。因此,这里必须再次检查前提条件。
1 #include <iostream> 2 #include <stdlib.h> 3 #include <boost/thread.hpp> 4 #include <boost/date_time/posix_time/posix_time.hpp> 5 6 using namespace std; 7 8 int num = 0; 9 boost::mutex me; 10 void Add1() 11 { 12 int i=0; 13 while(i<10) 14 { 15 me.lock(); 16 { 17 num = num+1; 18 cout<<"Add1:"<<num<<endl; 19 } 20 me.unlock(); 21 i++; 22 boost::this_thread::sleep(boost::posix_time::millisec(50)); 23 } 24 } 25 26 void Sub2() 27 { 28 int i=0; 29 while(i<10) 30 { 31 me.lock(); 32 { 33 num = num-2; 34 cout<<"Sub2:"<<num<<endl; 35 } 36 me.unlock(); 37 i++; 38 boost::this_thread::sleep(boost::posix_time::millisec(100)); 39 } 40 } 41 42 43 44 void printOdd() 45 { 46 while(num<20) 47 { 48 //me.lock(); 49 //if(num%2==0) 50 //{ 51 // cout<<"Odd:"<<++num<<endl; 52 //} 53 //me.unlock(); 54 55 if(num%2==0) 56 { 57 me.lock(); 58 if(num%2==0) 59 { 60 cout<<"Odd:"<<++num<<endl; 61 } 62 me.unlock(); 63 } 64 boost::this_thread::sleep(boost::posix_time::millisec(50)); 65 } 66 } 67 68 69 void printEven() 70 { 71 while(num<20) 72 { 73 //me.lock(); 74 //if(num%2==1) 75 //{ 76 // cout<<"Even:"<<++num<<endl; 77 //} 78 //me.unlock(); 79 80 if(num%2==1) 81 { 82 me.lock(); 83 if(num%2==1) 84 { 85 cout<<"Even:"<<++num<<endl; 86 } 87 me.unlock(); 88 } 89 boost::this_thread::sleep(boost::posix_time::millisec(100)); 90 } 91 } 92 93 94 int _tmain(int argc, _TCHAR* argv[]) 95 { 96 //boost::thread t1(Add1); 97 //boost::thread t2(Sub2); 98 99 boost::thread t1(printOdd); 100 boost::thread t2(printEven); 101 102 t1.join(); 103 t2.join(); 104 105 system("pause"); 106 return 0; 107 }