C++ 练习-多线程

匿名 (未验证) 提交于 2019-12-03 00:22:01
#if 0  //CreateThread代码示例 #include<iostream> #include<windows.h> using namespace std; DWORD WINAPI ThreadFun(LPVOID lpThreadParameter) {     char* str = (char*)lpThreadParameter;     while (true)     {         cout << "线程处理函数中接收到的参数是:" << str << endl;         cout << "子线程ID: " << GetCurrentThreadId() << endl;          Sleep(1000);     }      return 0;  } int main() {     DWORD threadId = 0;     HANDLE hThread = CreateThread(         NULL,     //设为NULL表示默认安全性         0,        //如果设为0,那么默认将使用与调用该函数的线程相同的栈空间大小                      ThreadFun,//线程处理函数,函数名就是函数指针         "hello thread!",//向线程函数传入的参数         0,              //0表示创建后马上运行         &threadId);     if (hThread == NULL){         cout << "线程创建失败,ERROR CODE : " << GetLastError() << endl;     }     cout << "线程的句柄:" << hThread << endl;     cout << "子线程的ID:" << threadId << endl;     cout << "主线程的ID:" << GetCurrentThreadId() << endl;      //关闭线程句柄,引用计数-1,并没有结束线程     //CloseHandle(hThread);//表示以后不再引用句柄     getchar();      //挂起线程     SuspendThread(hThread);     getchar();      //恢复执行线程     ResumeThread(hThread);     getchar();      return 0; } #endif #if 0//多线程间消息通讯 #include<iostream> #include<windows.h> #include<stdio.h> //自定义消息必须自定义在用户消息以上的数值 #define MY_MSG WM_USER+1 bool flag = true;  DWORD WINAPI ThreadFun1(LPVOID  param) {     //接收第二个线程发来的消息     MSG msg; #if 0 //GetMessage 如果有消息继续,否则阻塞     while (GetMessage(         &msg,//接收消息的线程ID         NULL,//取得消息的窗口的句柄,当为NULL时获取所属线程的消息         0,   //指定被检索的最小消息值的整数         0    //指定被检索的最大消息值的整数         ))     {         switch (msg.message){         case MY_MSG:             printf("收到消息:%d\n", (int)msg.wParam);             break;         //case WM_QUIT:         //  printf("收到WM_QUIT消息,退出!\n");//因为WM_QUIT消息会让GetMessage返回false所以不会进人循环         //  break;         }     }     printf("收到WM_QUIT消息,退出!\n"); #endif  #if 1 //PeekMessage的用法 不阻塞线程     while (flag)     {         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){//得到消息返回非零,否则返回0值             switch (msg.message){             case MY_MSG:                 printf("收到消息:%d\n", (int)msg.wParam);                 break;             case WM_QUIT:                 printf("收到QUIT消息,退出!\n");                 flag = false;                 break;             }         }     }  #endif       return 0;  }  DWORD WINAPI ThreadFun2(LPVOID  param) {     //给第一个线程发送消息     DWORD threadId = (DWORD)param;     int N = 1;     while (TRUE){         if (N <= 3){             PostThreadMessage(threadId, MY_MSG, (WPARAM)N++, NULL);         }         else{             PostThreadMessage(threadId, WM_QUIT, NULL, NULL);             break;         }         Sleep(1000);     }     return 0; } int  main() {     DWORD threadID = 0;     HANDLE hthread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, &threadID);     HANDLE hthread2 = CreateThread(NULL, 0, ThreadFun2, (LPVOID)threadID, 0, NULL);      HANDLE hArr[] = { hthread1, hthread2 };     WaitForMultipleObjects(2, hArr, TRUE, INFINITE);      //getchar();     system("pause");      return 0; } #endif  #if 0//静态TLS(线程本地存储变量) #include<iostream> #include<Windows.h> #include<stdio.h> //声明为静态TLS(线程本地存储变量) __declspec(thread) int N = 0;//每个线程中的值互不影响  DWORD WINAPI ThreadFun1(LPVOID param){     char *name = reinterpret_cast<char *>(param);//()还不能少     while (TRUE){         printf("线程%s打印:%d\n", name, ++N);         Sleep(1000);     } } DWORD WINAPI ThreadFun2(LPVOID param){     char *name = reinterpret_cast<char *>(param);//()还不能少     while (TRUE){         printf("\t\t\t线程%s打印:%d\n", name, ++(++N));         Sleep(1000);     } } void main(){     HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, "thread1", 0, NULL);     HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun2, "thread2", 0, NULL);      HANDLE hArr[] = { hThread1, hThread2 };     WaitForMultipleObjects(2, hArr, TRUE, INFINITE);      system("pause"); }  #endif #if 0//动态TLS(Thread Local Storage) #include<iostream> #include<stdio.h> #include<Windows.h>  DWORD WINAPI ThreadFun1(LPVOID param); DWORD WINAPI THreadFun2(LPVOID param); //动态TLS的索引 DWORD tlsIndex = 0;  int main() {     tlsIndex = TlsAlloc();//返回索引     if (tlsIndex == TLS_OUT_OF_INDEXES){         printf("分配TLS索引失败!\n");         return 0;     }     //在主线程中设置一个值     TlsSetValue(tlsIndex, "main cpp");     char *pName = (char*)TlsGetValue(tlsIndex);     printf("主线程打印: %s\n", pName);      HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, "A", 0, NULL);     HANDLE hThread2 = CreateThread(NULL, 0, THreadFun2, "B", 0, NULL);      HANDLE hArr[] = { hThread1, hThread2 };     WaitForMultipleObjects(2, hArr, TRUE, INFINITE);//等待两个线程执行完毕      TlsFree(tlsIndex);     system("pause");     return  0; } DWORD WINAPI ThreadFun1(LPVOID param){     TlsSetValue(tlsIndex, "hello");     while (true)     {         char *p = (char*)TlsGetValue(tlsIndex);         printf("线程A打印:%s\n", p);         Sleep(1000);      } } DWORD WINAPI THreadFun2(LPVOID param){     TlsSetValue(tlsIndex, "world");     while (true)     {         char *p = reinterpret_cast<char *>(TlsGetValue(tlsIndex));         printf("\t\t\t线程B打印:%s\n", p);         Sleep(1000);     } }   #endif  #if 0//利用事件Event实现买票程序 #include<iostream> #include<Windows.h> #include<stdio.h> #include<process.h>//_beginthread  void __cdecl SellThread1(void* param); void __cdecl SellThread2(void* param); int tickets = 100;  //个INVALID_HANDLE_VALUE ( vs2008下为0xfffffffff ) 实际值等于-1 //INVALID_HANDLE_VALUE类似与指针里的NULL,如果将指针释放后,应该立即将指针赋为NULL,否则出现野指针; //同理,句柄执行closehandle后,应该立即将句柄置为INVALID_HANDLE_VALUE,即让句柄失效。 HANDLE hEvent = INVALID_HANDLE_VALUE; int main() {     //创建事件,此刻为有信号状态,自动重置信号状态,初始化为有信号状态,线程可以直接获取     hEvent = CreateEvent(NULL, FALSE, TRUE, L"事件对象");     Sleep(1000);     //主线程休眠1秒后,将信号量置为无信号状态     //ResetEvent(hEvent);      printf("开始卖票了!\n");      //创建两个售票线程     uintptr_t t1 = _beginthread(SellThread1, 0, "售票窗口A");     uintptr_t t2 = _beginthread(SellThread2, 0, "售票窗口B");      //无限等待两个线程全部执行完毕     HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };     WaitForMultipleObjects(2, hArr, TRUE, INFINITE);      printf("卖票结束!\n");      system("pause");     return 0; } void __cdecl SellThread1(void* param){     char *name = reinterpret_cast<char*>(param);     while (tickets > 0){         //如果事件对象为信号状态(没有线程拥有它),则线程可以获取它后继续执行         //自动重置的事件对象,调用了WaitForSingleObject函数之后,自动重置为无信号,         //即其他线程不能再抢占了         WaitForSingleObject(hEvent, INFINITE);         if (tickets > 0){             Sleep(10);         }         //让事件变成有信号状态,相当于解锁         SetEvent(hEvent);     } } void __cdecl SellThread2(void* param){     char *name = reinterpret_cast<char*>(param);     while (tickets > 0){         WaitForSingleObject(hEvent, INFINITE);         if (tickets > 0){             Sleep(10);             printf("%s卖出第%d张票!\n", name, tickets--);         }         SetEvent(hEvent);     } } #endif  #if 0//利用事件对象实现一个程序只允许运行一个进程 #include<iostream> #include<windows.h> #include<stdio.h>  int main() {     HANDLE hEvent = CreateEvent(NULL, FALSE, TRUE, L"事件对象");     if (GetLastError() == ERROR_ALREADY_EXISTS){         printf("程序已经运行了,退出!\n");         getchar();          CloseHandle(hEvent);         return 0;     }     printf("程序第一次运行!\n");     getchar();     return 0; }  #endif  #if 0//利用semaphore实现程序只允许一个进程运行 #include<iostream> #include<Windows.h> #include<stdio.h>  int main() {     HANDLE hSemaphore = CreateSemaphore(NULL, 3, 3, L"停车位");     if (GetLastError() == ERROR_ALREADY_EXISTS){         printf("程序已经运行,请不要开启多个进程!\n");         getchar();         CloseHandle(hSemaphore);         return 0;     }     printf("程序第一次运行!\n");     getchar();     CloseHandle(hSemaphore);     return 0; } #endif #if 0 //采用互斥体来实现单进程运行 #include<iostream> #include<Windows.h> #include<stdio.h>   int main() {     HANDLE hMutex = CreateMutex(NULL, FALSE, L"售票互斥体");     if (GetLastError() == ERROR_ALREADY_EXISTS){         printf("程序已经运行,退出\n");         getchar();          CloseHandle(hMutex);         return 0;     }     printf("第一次运行程序!\n");     getchar();     return 0; } #endif #if 0  //信号量控制停车场车位 #include<windows.h> #include<stdio.h> DWORD WINAPI ThreadFun(LPVOID param); struct Car{     char name[20];     DWORD time; }; HANDLE hSemphore = INVALID_HANDLE_VALUE;  int main() {     //初始化三个停车位资源     hSemphore = CreateSemaphore(NULL, 3, 3, L"停车场");     HANDLE hArr[5] = { INVALID_HANDLE_VALUE };     for (int i = 0; i < 5; ++i){         Car *pCar = new Car;         sprintf_s(pCar->name, "车辆%c", 'A' + i);         pCar->time = 3 + i * 3;          //创建车辆线程         hArr[i] = CreateThread(NULL, 0, ThreadFun, (LPVOID)pCar, 0, NULL);     }     //等待所有线程执行完毕     WaitForMultipleObjects(5, hArr, true, INFINITE);     return 0; }  DWORD WINAPI ThreadFun(LPVOID param) {     //如果有剩余车位资源(有信号状态),就放行(往下执行)     WaitForSingleObject(hSemphore, INFINITE);     Car *pCar = reinterpret_cast<Car*>(param);     printf("%s进入停车场,停车%d秒!\n", pCar->name, pCar->time);     Sleep(pCar->time * 1000);     printf("%s离开停车场!\n", pCar->name);      //释放一个停车位(信号量+1)     ReleaseSemaphore(hSemphore, 1, NULL);      return 0; }  #endif  #if 0//互斥体 售票 #include<iostream> #include<process.h> #include<stdio.h> #include<windows.h>  void __cdecl SellThread1(void* param); void __cdecl SellThread2(void* param); int tickets = 100; HANDLE hMutex = INVALID_HANDLE_VALUE;  int main() {     hMutex = CreateMutex(NULL, FALSE, L"售票互斥体");      printf("开始卖票了!\n");      uintptr_t t1 = _beginthread(SellThread1, 0, "售票窗口A");     uintptr_t t2 = _beginthread(SellThread2, 0, "售票窗口B");      HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };     WaitForMultipleObjects(2, hArr, true, INFINITE);     printf("卖票结束!\n");     system("pause");     return 0;  } void __cdecl SellThread1(void* param){     char *name = reinterpret_cast<char *>(param);     while (tickets > 0){         //如果这个互斥体为有信号状态(没有线程拥有它),则线程获取它后继续执行         WaitForSingleObject(hMutex, INFINITE);         if (tickets > 0){             Sleep(10);             //CPU恰好执行到这里,这个时候线程的时间片到了,并且此时还剩最后一张票             printf("%s卖出第%d张票!\n", name, tickets--);         }         //释放对互斥体的拥有权 ,它变成有信号状态         ReleaseMutex(hMutex);     } } void __cdecl SellThread2(void* param){     char *name = reinterpret_cast<char *>(param);     while (tickets > 0){         WaitForSingleObject(hMutex, INFINITE);         if (tickets > 0){             Sleep(10);             printf("%s卖出第%d张票!\n", name, tickets--);         }         ReleaseMutex(hMutex);     } }   #endif  #if 0 //pv操作  生产者 消费者模式 P操作指:通过  V操作指:释放 #include<windows.h> #include<queue> #include<process.h> using namespace std;  queue<int> store; int StoreSize = 3;//仓库可以放3个货物  int ID = 1;//货物起始ID //随机时间数组,模拟随机生产和消费的速度 int arr1[10] = { 2, 1, 3, 5, 9, 2, 5, 2, 3, 7 };  //需要两个Event来通知 HANDLE hEvent1 = INVALID_HANDLE_VALUE;//有货物时通知消费者去取货物 HANDLE hEvent2= INVALID_HANDLE_VALUE;//仓库有空时通知生产者开始生产 //生产者 void ProducerThread(LPVOID param); //消费者 void ConsumerThread(LPVOID param);  int main() {     //需要先开始生产     hEvent1 = CreateEvent(NULL, TRUE, TRUE, L"事件对象1");     //一开始,仓库没货取     hEvent2 = CreateEvent(NULL, TRUE, FALSE, L"事件对象2");     uintptr_t t1 = _beginthread(ProducerThread, 0, NULL);     uintptr_t t2 = _beginthread(ConsumerThread, 0, NULL);     //无限等待两个线程运行结束     HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };     WaitForMultipleObjects(2, hArr, TRUE, INFINITE);      CloseHandle(hEvent1);     CloseHandle(hEvent2);      system("pause");      return 0; } //生产者 void ProducerThread(LPVOID param){     while (true)     {         WaitForSingleObject(hEvent1, INFINITE);//看event是否允许生产         if (store.size() < StoreSize)//仓库有空才生产         {             int id = ID++;             printf("生产货物:%d\n", id);             store.push(id);             Sleep(arr1[id % 10] * 1000);         }         else{//仓库满了             ResetEvent(hEvent1);//把事件设为无信号状态             printf("仓库满了!\n");         }         //如果仓库有货可以通知消费者来取货物了         if (store.size() > 0){             SetEvent(hEvent2);//让消费者的事件对象有信号         }      } } //消费者 void ConsumerThread(LPVOID param){     while (true)     {         //看event2是否允许取货物         WaitForSingleObject(hEvent2, INFINITE);         if (store.size() > 0){             int id = store.front(); store.pop();//获取队列中的货物             printf("\t\t\t取出货物:%d\n", id);             Sleep(arr1[(id + 3) % 10] * 1000);         }         else{//仓库空了             ResetEvent(hEvent2);//设为无信号,不能取货物了             printf("\t\t\t仓库空了!\n");         }         if (store.size() < 3){             SetEvent(hEvent1);//通知生产者继续生产         }     } }  #endif   //-------------------- C++11 多线程 ------------------------- #if 0//原子操作  线程并发,非原子操作错误演示 #include<iostream> #include<atomic>//原子操作头文件 #include<thread>  using namespace std; enum {     T=100000 }; //atomic<int> N = 0; int N = 0; void ThreadFun(){     for (int i = 0; i < T/*2*T*/; ++i){         ++N;//线程并发导致叠加操作,不是原子操作,因此肯定少于2T     } }  int main(){     thread t1(ThreadFun);     thread t2(ThreadFun);      t1.join();     t2.join();      cout << N << endl;     system("pause"); }  #endif  #if 0//原子操作   #include<iostream> #include<atomic>//原子操作头文件 #include<thread>  using namespace std; enum {     T = 1000000 }; atomic<int> N = 0;//原子操作,避免多线程并发导致的叠加操作 //int N = 0; void ThreadFun(){     for (int i = 0; i < T/*2*T*/; ++i){         ++N;     } }  int main(){     thread t1(ThreadFun);     thread t2(ThreadFun);      t1.join();     t2.join();      cout << N << endl;     system("pause"); }  #endif #if 0//原子操作,十人赛跑 #include<iostream> #include<atomic> #include<thread> #include<vector>  using namespace std; using namespace std::this_thread; atomic<bool> ready = false;//是否枪响  atomic_flag win = ATOMIC_FLAG_INIT;//终点线 void Run(int id){     //抢没响不能跑     while (!ready)     {         yield();//让其他线程先执行     }     for (int i = 0; i < 100000000; ++i){}     //如果没有设置过,返回false     if (!win.test_and_set()){         cout << id << " 号选手赢得第一名!" << endl;     }  } int main(int id){     //十个选手赛跑     vector<thread> vecPlayer;     for (int i = 0; i < 10; ++i){         vecPlayer.push_back(thread(Run, i));     }     cout << "十个选手已经准备好了!" << endl;     //准备发命令     //sleep_for(chrono::seconds(3));     cout << "...3..." << endl;     sleep_for(chrono::seconds(1));     cout << "...2..." << endl;     sleep_for(chrono::seconds(1));     cout << "...1..." << endl;     //可以跑了     ready = true;      //等待所有选手跑完     for (thread &t : vecPlayer){         t.join();     }      system("pause");     return 0; } #endif  #if 0   //C++11 互斥锁-1  #include<iostream> #include<mutex> #include<thread> #include<stdexcept> using namespace std; using  namespace  std::this_thread; mutex  m;  void  ThreadFun() {     try     {         for (int i = 0; i < 10; ++i)         {             sleep_for(chrono::seconds(1));             m.lock();             //lock_guard<mutex>   lck(m);//哪怕发生异常也是可以安全解锁,因为lck会析构,然后解锁mutex              if (i == 3)  throw   logic_error("发生异常了!");//发生异常后m无法解锁,线程无法结束,所以程序会锁死无法向下执行              cout << "A打印" << i << endl;              m.unlock();//抛出异常时,导致没有unlock,使得B无法获取mutex, 死锁          }      }     catch (logic_error  & e)     {         cout << "错误:" << e.what() << endl;      }  }  void  ThreadFun2() {     for (int i = 0; i < 10; ++i)     {         sleep_for(chrono::seconds(1));          //lock_guard<mutex>   lck(m);          m.lock();          cout << "B打印" << i << endl;         m.unlock();      } }   int  main() {      thread  t1(ThreadFun);     thread  t2(ThreadFun2);      t1.join();     t2.join();       return 0; }  #endif   #if 0  //C++11 互斥锁-2  #include<iostream> #include<mutex> #include<thread> #include<stdexcept> using namespace std; using  namespace  std::this_thread; mutex  m;  void  ThreadFun() {     try     {         for (int i = 0; i < 10; ++i)         {             sleep_for(chrono::seconds(1));             //m.lock();             lock_guard<mutex>   lck(m);//哪怕发生异常也是可以安全解锁,因为lck会析构,然后解锁mutex              if (i == 3)  throw   logic_error("发生异常了!");              cout << "A打印" << i << endl;              //m.unlock();//抛出异常时,导致没有unlock,使得B无法获取mutex, 死锁          }      }     catch (logic_error  & e)     {         cout << "错误" <<e.what()<< endl;     }  }  void  ThreadFun2() {     for (int i = 0; i < 10; ++i)     {         sleep_for(chrono::seconds(1));          lock_guard<mutex>   lck(m);          //m.lock();          cout << "B打印" << i << endl;          //m.unlock();      } }   int  main() {      thread  t1(ThreadFun);     thread  t2(ThreadFun2);      t1.join();     t2.join();       return 0; }  #endif  #if 0//独占锁 #include<iostream> #include<mutex> #include<thread> #include<stdexcept> using namespace std; using namespace std::this_thread; mutex m; void threadFun1(){     try{         for (int i = 0; i < 10; i++)         {             unique_lock<mutex> lck(m);             //m.lock();//             if (i == 3)                 throw logic_error("发生异常了!");             cout << "A 打印: " << i << endl;              //m.unlock();//使用lck.lock()主动上锁,当抛出异常时,导致没有unlock,使得B无法获取mutex,死锁             //但是使用unique_lock则不会出现死锁的情况,离开作用于会自动解锁,但是也可以手动lck.unlock()来手动解锁             sleep_for(chrono::seconds(1));         }     }     catch (logic_error &e){         cout << "错误" << e.what() << endl;     } } void threadFun2(){     for (int i = 0; i < 10; i++)     {         unique_lock<mutex> lok(m);         cout << "打印B: " << i << endl;         //lok.unlock();//可以手动解锁,也可以不用         sleep_for(chrono::seconds(1));     } } int main() {     thread t1(threadFun1);     thread t2(threadFun2);      t1.join();     t2.join();      system("pause");     return 0; } #endif  #if  0 #include<iostream> #include<mutex> #include<condition_variable> #include<thread> using namespace std; using namespace std::this_thread; using namespace std::chrono;  condition_variable cv;//仅支持unique_lock<mutex>作为wait的参数 condition_variable_any cv2;//接受任何lockable参数作为wait的参数 mutex m;  void ThreadFun(int id){     unique_lock<mutex> lck(m);      cv.wait(lck);//等待被唤醒,否则一直卡在这里     cout << "线程ID: " << id << "执行!" << endl; }  int main(){     thread t1(ThreadFun, 1);     thread t2(ThreadFun, 2);     thread t3(ThreadFun, 3);      cout << "3秒后被唤醒" << endl;      sleep_for(seconds(3));//3秒后被唤醒      //cv.notify_all();//唤醒所有线程     t1.join();     t2.join();     t3.join();     system("pause");     return 0; }  #endif  #if 0 //async线程异步 #include<iostream> #include<future> #include<thread> using namespace std; using namespace std::this_thread; using namespace std::chrono;  int work(int a, int b) {     cout << "开始计算:" << endl;     sleep_for(seconds(5));//假设某个计算需要耗时5s     return a + b; } int main(){     future<int> result = async(work, 123, 456);//线程同步函数     result.wait(); //等待线程结束运行     cout << "算出结果:" << endl;     int sum = result.get();//获取线程返回的结果     cout << "最终的结果是: " << sum << endl;     system("pause");      return 0; } #endif #if 0 #include<iostream> #include<future> #include<thread> using namespace std; using namespace std::this_thread; using namespace std::chrono;  void work(promise<int> &prom){     cout << "开始计算!" << endl;     sleep_for(seconds(3));     cout << "计算完成!" << endl;     prom.set_value(666);//promise 设置结果值 可以被future  get到  } int main() {     //定义一个promise     promise<int> prom;     //future 和 promise 搭配使用,类似于aynsc     future<int> result = prom.get_future();      thread t1(work, ref(prom));     t1.detach();      int sum = result.get();     cout << "获取结果:" << sum << endl;      system("pause");      return 0; }   #endif 
文章来源: C++ 练习-多线程
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!