Q:

No need for mutex, race conditions not always bad, do they?

I'm getting this crazy idea that mutex synchronization can be omitted in some cases when most of us would typically want and would use mutex synchronization.
Ok suppose you have this case:
Buffer *buffer = new Buffer(); // Initialized by main thread;

...

// The call to buffer's `accumulateSomeData` method is thread-safe
// and is heavily executed by many workers from different threads simultaneously.
buffer->accumulateSomeData(data); // While the code inside is equivalent to vector->push_back()

...

// All lines of code below are executed by a totally separate timer
// thread that executes once per second until the program is finished.

auto bufferPrev = buffer; // A temporary pointer to previous instance

// Switch buffers, put old one offline
buffer = new Buffer();

// As of this line of code all the threads will switch to new instance 
// of buffer. Which yields that calls to `accumulateSomeData`
// are executed over new buffer instance. Which also means that old 
// instance is kinda taken offline and can be safely operated from a
// timer thread.

bufferPrev->flushToDisk(); // Ok, so we can safely flush
delete bufferPrev;

While it's obvious that during buffer = new Buffer(); there can still be uncompleted operations that add data on previous instance. But since disk operations are slow we get natural kind of barrier.
So how do you estimate the risk of running such code without mutex synchronisation?

Edit
It's so hard these days to ask a question in SO without getting mugged by couple of angry guys for no reason. 
Here is my correct in all terms code:
#include <cassert>

#include "leveldb/db.h"
#include "leveldb/filter_policy.h"

#include <iostream>
#include <boost/asio.hpp>
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/lockfree/stack.hpp>
#include <boost/lockfree/queue.hpp>
#include <boost/uuid/uuid.hpp>            // uuid class
#include <boost/uuid/uuid_io.hpp>         // streaming operators etc.
#include <boost/uuid/uuid_generators.hpp> // generators

#include <CommonCrypto/CommonDigest.h>

using namespace std;
using namespace boost::filesystem;

using boost::mutex;
using boost::thread;

enum FileSystemItemType : char {
    Unknown         = 1,
    File            = 0,
    Directory       = 4,

    FileLink        = 2,
    DirectoryLink   = 6
};

// Structure packing optimizations are used in the code below
// http://www.catb.org/esr/structure-packing/
class FileSystemScanner {
private:
    leveldb::DB *database;

    boost::asio::thread_pool pool;

    leveldb::WriteBatch *batch;

    std::atomic<int> queue_size;
    std::atomic<int> workers_online;
    std::atomic<int> entries_processed;
    std::atomic<int> directories_processed;
    std::atomic<uintmax_t> filesystem_usage;

    boost::lockfree::stack<boost::filesystem::path*, boost::lockfree::fixed_sized<false>> directories_pending;

    void work() {
        workers_online++;

        boost::filesystem::path *item;

        if (directories_pending.pop(item) && item != NULL)
        {            
            queue_size--;

            try {
                boost::filesystem::directory_iterator completed;
                boost::filesystem::directory_iterator iterator(*item);

                while (iterator != completed)
                {
                    bool isFailed = false, isSymLink, isDirectory;

                    boost::filesystem::path path = iterator->path();

                    try {
                        isSymLink = boost::filesystem::is_symlink(path);
                        isDirectory = boost::filesystem::is_directory(path);

                    } catch (const boost::filesystem::filesystem_error& e) {
                        isFailed = true;
                        isSymLink = false;
                        isDirectory = false;
                    }

                    if (!isFailed)
                    {
                        if (!isSymLink) {
                            if (isDirectory) {
                                directories_pending.push(new boost::filesystem::path(path));

                                directories_processed++;

                                boost::asio::post(this->pool, [this]() { this->work(); });

                                queue_size++;
                            } else {
                                filesystem_usage += boost::filesystem::file_size(iterator->path());
                            }
                        }
                    }

                    int result = ++entries_processed;

                    if (result % 10000 == 0) {
                        cout << entries_processed.load() << ", " << directories_processed.load() << ", " << queue_size.load() << ", " << workers_online.load() << endl;
                    }

                    ++iterator;
                }

                delete item;
            } catch (boost::filesystem::filesystem_error &e) {

            }
        }

        workers_online--;
    }

public:
    FileSystemScanner(int threads, leveldb::DB* database):
        pool(threads), queue_size(), workers_online(), entries_processed(), directories_processed(), directories_pending(0), database(database)
    {
    }

    void scan(string path) {
        queue_size++;

        directories_pending.push(new boost::filesystem::path(path));

        boost::asio::post(this->pool, [this]() { this->work(); });
    }

    void join() {
        pool.join();
    }
};

int main(int argc, char* argv[])
{
    leveldb::Options opts;

    opts.create_if_missing = true;
    opts.compression = leveldb::CompressionType::kSnappyCompression;
    opts.filter_policy = leveldb::NewBloomFilterPolicy(10);

    leveldb::DB* db;

    leveldb::DB::Open(opts, "/temporary/projx", &db);

    FileSystemScanner scanner(std::thread::hardware_concurrency(), db);

    scanner.scan("/");
    scanner.join();

    return 0;
}

My question is: Can I omit synchronization for batch which I'm not using yet? Since it's thread-safe and it should be enough to just switch buffers before actually committing any results to disk?

A:

You have a serious misunderstanding. You think that when you have a race condition, there are some specific list of things that can happen. This is not true. A race condition can cause any kind of failure, including crashes. So absolutely, definitely not. You absolutely cannot do this.
That said, even with this misunderstanding, this is still a disaster.
Consider:
buffer = new Buffer();

Suppose this is implemented by first allocating memory, then setting buffer to point to that memory, and then calling the constructor. Other threads may operate on the unconstructed buffer. boom.
Now, you can fix this. But it's just one the many ways I can imagine this screwing up. And it can screw up in ways that we're not clever enough to imagine. So, for all that is holy, do not even think of doing this ever again.

