为什么我要在全局级别定义mongoDB集合 - 它的线程安全

时间:2017-06-23 18:49:55

标签: multithreading mongodb concurrency c++-cli mongodb-csharp-2.0

我正在使用C ++ / Cli来处理编译为dll的mongoDB最新C#驱动程序。我在C ++代码中使用了驱动程序的实例。

我已多次尝试过。如果我构建多个线程,每个线程都尝试更新同一个集合中的文档,那么似乎只有一个线程会成功。当我为线程设置休眠时间时,似乎工作正常。但我需要在短时间内同时更新数千个文件,设置睡眠时间不是一种有效的方法。

以下是线程的启动方式:

void updateKOOnMongo(int i, int k) {
    time_t tn = time(NULL);
    Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
    lastkoupdatetime = time(NULL);
    MongoUpdates ^mgudt = gcnew MongoUpdates(i, k);
    Thread ^updateko = gcnew Thread(gcnew ThreadStart(mgudt, &MongoUpdates::UpdateKO));
    updateko->Start();
}

以下是MongoUpdates中的函数:

    void MongoUpdates::UpdateKO {
        mongoImp->updateKO(i, k);
    }

mongoImp is an instance of the mongoDB C# driver compiled as dll.

以下是C#驱动程序中的代码:

    public static async void updateKO(int i, int k)
    {
        await updateKOdr(i, k);
    }

    static async Task updateKOdr(int i, int k)
    {
        string col = "ko." + i.ToString();
        var collection = _database.GetCollection<BsonDocument>(col);
        var builder = Builders<BsonDocument>.Filter;
        var filter = builder.Eq("a", i) & builder.Lte("lf", k);
        var update = Builders<BsonDocument>.Update.Set("status", 0);
        var result = await collection.UpdateOneAsync(filter, update);
    }

如果删除以下部分:

time_t tn = time(NULL);
Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
lastkoupdatetime = time(NULL);

如果两个或多个线程同时处理同一个集合,它几乎总是会失败。请帮忙。

1 个答案:

答案 0 :(得分:0)

我发现问题是我在每次更新操作中都创建了一个新的集合实例。这很糟糕,我没注意到,因为代码是很久以前写的,当时我对mongoDB很新。 mongoDB集合是线程安全的,所以我应该在全局级别定义它:

protected static IMongoCollection<BsonDocument> _collection;

所以我可以使用它而不必每次都创建它的新实例。我只需要这样做:

if (_collection == null) {
   _collection = _database.GetCollection<BsonDocument>("ko." + i.ToString());
}