2017-08-31 3 views
3

redisがシングルスレッドサーバーの場合、結果は100000ではないのはなぜですか?私はそれが赤目の問題ではないと思うが、理由を知りたい。ありがとう。redisで非同期問題が発生する

 RedisConnection.Default.Database.StringSet("mykey1", 0); 
     Parallel.For(0, 50000, new ParallelOptions { MaxDegreeOfParallelism = 2 }, (i) => 
     { 
      var number = RedisConnection.Default.Database.StringGet("mykey1"); 
      int result = int.Parse(number); 
      RedisConnection.Default.Database.StringSet("mykey1", result + 1); 

     }); 
     Console.WriteLine("Result" + RedisConnection.Default.Database.StringGet("mykey1")); 
+4

あなたの操作は[原子](HTTPSではありません。 org/wiki/Atomicity_(データベースシステム))。それは赤字のせいではない。あなたのコードはスレッドセーフではありません。つまり、2つのスレッドは同じ値を読み取ることができます。そして、もちろん、彼らは同じ価値を書くでしょう。必要な動作を得るには、一度に1つのスレッドだけが読み取りと書き込みの1サイクルを実行できるようにする必要があります。 – Fildor

+0

この特定のケースでは、それはParallelの使用をかなり役に立たなくするでしょう。 – Fildor

+0

ありがとうございます。 2スレッドは同じ値を読み取ることができます! –

答えて

0

この問題を回避するには、MULTI/EXECを使用できます。 2つのコマンドが別のコマンドで分割されないようにします。それは取引になります。

0

トランザクションブロック(MULTI/EXEC)を使用せずにRedisを2回別々に呼び出しているため、StringGetStringSet操作はアトミックではありません。スレッドの実行は、GetおよびSet操作をインターリーブできます。

約一つの可能​​な実行順序を考える:

  1. スレッド1がスレッド2がmyKey1は= 40
  2. スレッド2が41
  3. スレッド2がmyKey1 = 41
  4. スレッド2を読み出してMYKEYの読み書きを行うmyKey1 = 40
  5. を読み込みmyKeyの書き込み42
  6. スレッド1 myKey1の書き込み41

このコードを書くための適切な方法は、StringIncrementに呼び出してStringGetStringSetに別のコールを交換することです://en.wikipedia:

RedisConnection.Default.Database.StringSet("mykey1", 0); 
    Parallel.For(0, 50000, new ParallelOptions { MaxDegreeOfParallelism = 2 }, (i) => 
    { 
     RedisConnection.Default.Database. StringIncrement("mykey1"); 
    }); 
    Console.WriteLine("Result" + RedisConnection.Default.Database.StringGet("mykey1")); 
関連する問題