简体   繁体   中英

right way to write to file from different threads (using Qt c++ )

i have thread pool that create threads each thread worker calculate some work and when it done it writes the result to file , there is only 1 result file , that each worker thread needs to write to .
now my question is how i guarantee that there wouldn't be any locks or missing write data to the file where allot of threads trying to write to single file ? what is the right strategy for such scenario?
mybe keep all result in memory ? or chanks of results

im using already the QThreadPool framework , and i need to find solution with it.
also i wander , does writing to single file from worker threads , i will have to use
singleton file manager or static class , is it good idea? for multithreaded app ?

So you have many concurrent threads competing for one shared resource. That begs a synchronization primitive of some sort, for example a mutex .

Here's (non-Qt specific) code showcasing 10 threads simultaneously writing to a single file. On a side note, C++11 introduced a lot of goodies like std::mutex (and std::thread too, so that can help eliminate some Qt-specific threading code).

#include <fstream>   
#include <mutex>
#include <thread>    
#include <vector>

std::mutex m;
std::ofstream file;

int main() {
  file.open("file.txt");

  std::vector<std::thread> workers;
  for (int i = 0; i < 10; ++i) {       
    workers.push_back(std::thread([=i] {
      for (int j = 0; j < 10; ++j) {
        std::lock_guard<std::mutex> lock(m);
        file << "thread " << i << ": " << j << endl;
      }
    }));
  }
  for (auto& worker : workers) {
    worker.join();
  }

  file.close();
  return 0;
}

Of course, if you have a lot of places in your code accessing the shared resource, it's better to encapsulate it, along with the mutex, in some "accessor" class that would manage all state-modifying calls to the resource.

PS If you're not on C++11 compiler, you can use boost::mutex or Qt-specific mutex wrapper. The key thing is that you need some synchronization primitive associated with the shared resource.

As I assume, you crate your own Runnable , deriving from QRunnable

You can pass some context information when constructing your Runnable class. You need to pass device to write in and mutex to lock device, for example.

class Runnable: public QRunnable
{
public:
    Runnable(QIOdevice* device, QMutex* mutex):_d(device), _m(mutex){}
    void run()
    {
        saveInFile();
    }

private:
    void saveInFile()
    {
        QMutexLocker lock(_m);
        //now only one thread can write to file in the same moment of time
        device->write(...);
    }

    QIOdevice* _d;
    QMutex* _m;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM