TinyThread计数器 - 便携式c++0和c++11线程间通信变得简单

TinyThread counter - portable c++0 and c++11 inter thread communication made simple

本文关键字:通信 简单 线程 c++11 计数器 便携式 c++0 TinyThread      更新时间:2023-10-16

我看到这个例子是TinyThread c++库的一部分,并注意到它如何在辅助线程上增加gCount,然后由主线程打印。参见测试 5

/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2010-2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
    1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgment in the product documentation would be
    appreciated but is not required.
    2. Altered source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.
    3. This notice may not be removed or altered from any source
    distribution.
*/
#include <iostream>
#include <list>
#include <tinythread.h>
#include <fast_mutex.h>
using namespace std;
using namespace tthread;
// HACK: Mac OS X and early MinGW do not support thread-local storage
#if defined(__APPLE__) || (defined(__MINGW32__) && (__GNUC__ < 4))
 #define NO_TLS
#endif

// Thread local storage variable
#ifndef NO_TLS
thread_local int gLocalVar;
#endif
// Mutex + global count variable
mutex gMutex;
fast_mutex gFastMutex;
int gCount;
// Condition variable
condition_variable gCond;
// Thread function: Thread ID
void ThreadIDs(void * aArg)
{
  cout << " My thread id is " << this_thread::get_id() << "." << endl;
}
#ifndef NO_TLS
// Thread function: Thread-local storage
void ThreadTLS(void * aArg)
{
  gLocalVar = 2;
  cout << " My gLocalVar is " << gLocalVar << "." << endl;
}
#endif
// Thread function: Mutex locking
void ThreadLock(void * aArg)
{
  for(int i = 0; i < 10000; ++ i)
  {
    lock_guard<mutex> lock(gMutex);
    ++ gCount;
  }
}
// Thread function: Mutex locking
void ThreadLock2(void * aArg)
{
  for(int i = 0; i < 10000; ++ i)
  {
    lock_guard<fast_mutex> lock(gFastMutex);
    ++ gCount;
  }
}
// Thread function: Condition notifier
void ThreadCondition1(void * aArg)
{
  lock_guard<mutex> lock(gMutex);
  -- gCount;
  gCond.notify_all();
}
// Thread function: Condition waiter
void ThreadCondition2(void * aArg)
{
  cout << " Wating..." << flush;
  lock_guard<mutex> lock(gMutex);
  while(gCount > 0)
  {
    cout << "." << flush;
    gCond.wait(gMutex);
  }
  cout << "." << endl;
}
// Thread function: Yield
void ThreadYield(void * aArg)
{
  // Yield...
  this_thread::yield();
}
// Thread function: Detach
void ThreadDetach(void * aArg)
{
  // We don't do anything much, just sleep a little...
  this_thread::sleep_for(chrono::milliseconds(100));
}

// This is the main program (i.e. the main thread)
int main()
{
  // Test 1: Show number of CPU cores in the system
  cout << "PART I: Info" << endl;
  cout << " Number of processor cores: " << thread::hardware_concurrency() << endl;
  // Test 2: thread IDs
  cout << endl << "PART II: Thread IDs" << endl;
  {
    // Show the main thread ID
    cout << " Main thread id is " << this_thread::get_id() << "." << endl;
    // Start a bunch of child threads - only run a single thread at a time
    thread t1(ThreadIDs, 0);
    t1.join();
    thread t2(ThreadIDs, 0);
    t2.join();
    thread t3(ThreadIDs, 0);
    t3.join();
    thread t4(ThreadIDs, 0);
    t4.join();
  }
  // Test 3: thread local storage
  cout << endl << "PART III: Thread local storage" << endl;
#ifndef NO_TLS
  {
    // Clear the TLS variable (it should keep this value after all threads are
    // finished).
    gLocalVar = 1;
    cout << " Main gLocalVar is " << gLocalVar << "." << endl;
    // Start a child thread that modifies gLocalVar
    thread t1(ThreadTLS, 0);
    t1.join();
    // Check if the TLS variable has changed
    if(gLocalVar == 1)
      cout << " Main gLocalID was not changed by the child thread - OK!" << endl;
    else
      cout << " Main gLocalID was changed by the child thread - FAIL!" << endl;
  }
#else
  cout << " TLS is not supported on this platform..." << endl;
#endif
  // Test 4: mutex locking
  cout << endl << "PART IV: Mutex locking (100 threads x 10000 iterations)" << endl;
  {
    // Clear the global counter.
    gCount = 0;
    // Start a bunch of child threads
    list<thread *> threadList;
    for(int i = 0; i < 100; ++ i)
      threadList.push_back(new thread(ThreadLock, 0));
    // Wait for the threads to finish
    list<thread *>::iterator it;
    for(it = threadList.begin(); it != threadList.end(); ++ it)
    {
      thread * t = *it;
      t->join();
      delete t;
    }
    // Check the global count
    cout << " gCount = " << gCount << endl;
  }
  // Test 5: fast_mutex locking
  cout << endl << "PART V: Fast mutex locking (100 threads x 10000 iterations)" << endl;
  {
    // Clear the global counter.
    gCount = 0;
    // Start a bunch of child threads
    list<thread *> threadList;
    for(int i = 0; i < 100; ++ i)
      threadList.push_back(new thread(ThreadLock2, 0));
    // Wait for the threads to finish
    list<thread *>::iterator it;
    for(it = threadList.begin(); it != threadList.end(); ++ it)
    {
      thread * t = *it;
      t->join();
      delete t;
    }
    // Check the global count
    cout << " gCount = " << gCount << endl;
  }
  // Test 6: condition variable
  cout << endl << "PART VI: Condition variable (40 + 1 threads)" << endl;
  {
    // Set the global counter to the number of threads to run.
    gCount = 40;
    // Start the waiting thread (it will wait for gCount to reach zero).
    thread t1(ThreadCondition2, 0);
    // Start a bunch of child threads (these will decrease gCount by 1 when they
    // finish)
    list<thread *> threadList;
    for(int i = 0; i < 40; ++ i)
      threadList.push_back(new thread(ThreadCondition1, 0));
    // Wait for the waiting thread to finish
    t1.join();
    // Wait for the other threads to finish
    list<thread *>::iterator it;
    for(it = threadList.begin(); it != threadList.end(); ++ it)
    {
      thread * t = *it;
      t->join();
      delete t;
    }
  }
  // Test 7: yield
  cout << endl << "PART VII: Yield (40 + 1 threads)" << endl;
  {
    // Start a bunch of child threads
    list<thread *> threadList;
    for(int i = 0; i < 40; ++ i)
      threadList.push_back(new thread(ThreadYield, 0));
    // Yield...
    this_thread::yield();
    // Wait for the threads to finish
    list<thread *>::iterator it;
    for(it = threadList.begin(); it != threadList.end(); ++ it)
    {
      thread * t = *it;
      t->join();
      delete t;
    }
  }
  // Test 8: sleep
  cout << endl << "PART VIII: Sleep (10 x 100 ms)" << endl;
  {
    // Sleep...
    cout << " Sleeping" << flush;
    for(int i = 0; i < 10; ++ i)
    {
      this_thread::sleep_for(chrono::milliseconds(100));
      cout << "." << flush;
    }
    cout << endl;
  }
  // Test 9: detach
  cout << endl << "PART IX: Detach" << endl;
  {
    thread t(ThreadDetach, 0);
    t.detach();
    cout << " Detached from thread." << endl;
  }
}

所以我尝试制作自己的代码,但主线程不仅看不到变量增量,而且当我将睡眠添加到工作线程时,它不再尝试在主线程上打印变量。由于这两个问题,工作线程也永远不会退出。

#include <iostream>
#include <list>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
void workerThread(void * aArg)
{
  bool running = true;
  int number = 0;
  while(running)
  {
     lock_guard<fast_mutex> lock(workerThreadMutex);
     number++;
     cout << "secondThread::" << number << endl;
     this_thread::sleep_for(chrono::milliseconds(1000));
     if(killThread)
        running =true;
  }
}
int main()
{
    thread* wThread = new thread(workerThread, 0);
    bool running = true;
    while(running)
    {
        this_thread::sleep_for(chrono::milliseconds(100));
        if(workerThreadMutex.try_lock())
        {
            cout << "mainThread::" << number << endl;
            if(number == 100)
            {
                killThread = true;
                running = false;
            }
            workerThreadMutex.unlock();
        }
    }
    wThread->join();
    delete wThread;
    return 0;
}

你能帮忙吗?

编辑:对我的代码进行了更改

编辑:修复了局部变量问题,它现在可以工作了,除了没有检测到终止线程布尔值,因此辅助线程(工作线程(没有退出。

编辑:修复了局部变量的问题

编辑:修复了睡眠问题

编辑:修复了问题杀戮线程

编辑:所有问题都已修复

#include <iostream>
#include <list>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
  bool running = true;
void workerThread(void * aArg)
{
  while(running)
  {
    {
     lock_guard<fast_mutex> lock(workerThreadMutex);
     number++;
     if(killThread)
        running =false;
     }
     this_thread::sleep_for(chrono::milliseconds(50));
  }
}
int main()
{
    thread* wThread = new thread(workerThread, 0);
    while(running)
    {
        this_thread::sleep_for(chrono::milliseconds(100));
        if(workerThreadMutex.try_lock())
        {
            cout << "mainThread::" << number << endl;
            if(number > 100)
            {
                killThread = true;
                //running = false;
            }
            workerThreadMutex.unlock();
        }
    }
    wThread->join();
    delete wThread;
    return 0;
}

编辑:进一步修改以显示可移植的C ++ 11友好的线程间通信

#include <iostream>
#include <sstream>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
bool running = true;
string message = "";
void workerThread(void * aArg)
{
    while(running)
    {
        {
            lock_guard<fast_mutex> lock(workerThreadMutex);
            if(message=="")
            {
                number++;
                ostringstream Convert;
                Convert << number; 
                message = Convert.str();
            }
            if(killThread)
                running =false;
        }
        this_thread::sleep_for(chrono::milliseconds(1));
    }
}
int main()
{
    thread* wThread = new thread(workerThread, 0);
    bool stopMainThreadLoop = false;
    while(!stopMainThreadLoop)
    {
        this_thread::sleep_for(chrono::milliseconds(10));
        if(workerThreadMutex.try_lock())
        {
            //cout << "mainThread::" << number << endl;
            cout << "mainThread::" << message << endl;
            //if(number > 100)
            if(message == "100")
            {
                killThread = true;
                stopMainThreadLoop = true;
            }
            message = "";
            workerThreadMutex.unlock();
        }
    }
    wThread->join();
    delete wThread;
    return 0;
}

看看你的代码的这一部分

int number = 0;  // Global variable, i.e. will be used by main
void workerThread(void * aArg)
{
  bool running = true;
  int number = 0; // Local variable, i.e. will be used by in the function

因此,main正在使用一个变量,而函数(也称为线程(正在使用另一个变量。因此,main 看不到任何增量。

只需删除局部变量即可。

对于睡眠部分

我认为问题是你在保持互斥锁的同时睡觉。

试试这个:

void workerThread(void * aArg)
{
  bool running = true;
  //----------------------  int number = 0;
  while(running)
  {
     {
         lock_guard<fast_mutex> lock(workerThreadMutex);
         number++;
         //cout << "secondThread::" << number << endl;
         if(killThread)
            running =true;
     }
     this_thread::sleep_for(chrono::milliseconds(1000));
  }
}

对于杀戮:

试试这个

       if(number >= 100)    // Changed
        {
            killThread = true;
            running = false;
        }

函数内部

 if(killThread)
    running =true;  // Should be false