マルチスレッド環境でlongを共有するときの注意 (C#編)
id:nowokayがおもしろいことしてたので、.NETで試してみることにしました。
以下コード
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace VolatileSample { public class VolatileSample { static long lock_ = 0; public static void Main(string[] args) { new Thread(delegate() { for (; ; ) { long t; t = lock_; long high = t >> 32; long low = t & 0xffffffffL; if (high != low) { Console.WriteLine("おわた"); Process.GetCurrentProcess().Kill(); } } }).Start(); Random r = new Random(); for (; ; ) { long a = r.Next(); if (a < 0) a -= Int32.MinValue; long t = (a << 32) + a; lock_ = t; } } } }
案の定、.NETでもすぐ終了します。
で、Javaだとvolatile指定すればOKなんだけど、C#の場合は、longにはvolatile指定ができないようなので、lockするようにしてみます。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace VolatileSample { public class VolatileSample { static long lock_ = 0; static object lockObj = new object(); public static void Main(string[] args) { new Thread(delegate() { for (; ; ) { long t; lock (lockObj) { t = lock_; } long high = t >> 32; long low = t & 0xffffffffL; if (high != low) { Console.WriteLine("終了"); Process.GetCurrentProcess().Kill(); } } }).Start(); Random r = new Random(); for (; ; ) { long a = r.Next(); if (a < 0) a -= Int32.MinValue; long t = (a << 32) + a; lock (lockObj) { lock_ = t; } } } } }
これで終了しなくなりました。