質問
複数スレッドから読み書きを行う、共有オブジェクトの作成に悩んでいます。
オブジェクトは通信している一つ機器の状態を保持しています。
###条件
一つの機器の状態ですが、すべての状態において読み書きが同時にできないようしなくても
項目ごとに読み書きができなくなれば良いかなと考えております。
可読性が低くなりそうなら全体としても大丈夫です。
案
例として下記のようなDataManageクラスを使用しますが、
実際にはDataManageクラス内にその他情報もある想定です。
(DataManageは機器、State1/State2は機器の状態を項目分けしたものになります。)
項目を内部クラスとしていますが外でも大丈夫です。
C#
1 1、プロパティで公開せず関数による項目ごとのアクセスにする。 2 public class DataManage 3 { 4 public class State1 5 { 6 public int A { get; set; } 7 public int B { get; set; } 8 } 9 10 public class State2 11 { 12 public int C { get; set; } 13 public int D { get; set; } 14 } 15 16 private object syncState1 = new object(); 17 private object syncState2 = new object(); 18 private State1 state1 = new State1(); 19 private State2 state2 = new State2(); 20 21 public State1 GetState1() 22 { 23 var ret = new State1(); 24 lock (syncState1) 25 { 26 // ここでコピーなど 27 } 28 return ret; 29 } 30 public State2 GetState2() 31 { 32 var ret = new State2(); 33 lock (syncState2) 34 { 35 // ここでコピーなど 36 } 37 return ret; 38 } 39 public void SetState1(State1 state) 40 { 41 // ここでコピーなど 42 } 43 public void SetState2(State2 state) 44 { 45 // ここでコピーなど 46 } 47 /// <summary> 48 /// 必要によって個々の状態にアクセスできるように。。。 49 /// </summary> 50 public int GetState1A() 51 { 52 lock (syncState1) return state1.A; 53 } 54 public void SetState1A( int val ) 55 { 56 lock (syncState1) state1.A = val; 57 } 58 } 59 60 2、状態をさらにラップするクラスを設けプロパティでアクセスできるようにする。 61 public class DataManage 62 { 63 64 public class State1Lap 65 { 66 public class State1 67 { 68 public int A { get; set; } 69 public int B { get; set; } 70 } 71 72 private State1 state = new State1(); 73 private object syncState = new object(); 74 75 public int A 76 { 77 get { lock (syncState) return state.A; } 78 set { lock (syncState) state.A = value; } 79 } 80 public int B 81 { 82 get { lock (syncState) return state.B; } 83 set { lock (syncState) state.B = value; } 84 } 85 86 public State1 GetState() 87 { 88 var ret = new State1(); 89 lock (syncState) 90 { 91 // ここでこぴーなど 92 } 93 return ret; 94 } 95 96 public void SetState(State1 state) 97 { 98 // ここでこぴーなど 99 } 100 101 } 102 103 public class State2Lap 104 { 105 public class State2 106 { 107 public int C { get; set; } 108 public int D { get; set; } 109 } 110 111 private State2 state = new State2(); 112 private object syncState = new object(); 113 114 public int C 115 { 116 get { lock (syncState) return state.C; } 117 set { lock (syncState) state.C = value; } 118 } 119 public int D 120 { 121 get { lock (syncState) return state.D; } 122 set { lock (syncState) state.D = value; } 123 } 124 125 public State2 GetState() 126 { 127 var ret = new State2(); 128 lock (syncState) 129 { 130 // ここでこぴーなど 131 } 132 return ret; 133 } 134 135 public void SetState( State2 state ) 136 { 137 // ここでこぴーなど 138 } 139 } 140 private State1Lap state1 = new State1Lap(); 141 private State2Lap state2 = new State2Lap(); 142 143 public State1Lap State1 => state1; 144 public State2Lap State2 => state2; 145 } 146 147 3、そもそも項目ごとに分けずすべてを並列に管理する。 148 public class DataManage 149 { 150 private object syncState = new object(); 151 private int a { get; set; } 152 private int b { get; set; } 153 154 private int c { get; set; } 155 private int d { get; set; } 156 157 public int A 158 { 159 get { lock (syncState) return a; } 160 set { lock (syncState) a = value; } 161 } 162 public int B 163 { 164 get { lock (syncState) return b; } 165 set { lock (syncState) b = value; } 166 } 167 168 public int C 169 { 170 get { lock (syncState) return c; } 171 set { lock (syncState) c = value; } 172 } 173 public int D 174 { 175 get { lock (syncState) return d; } 176 set { lock (syncState) d = value; } 177 } 178 179 public DataManage Clone() 180 { 181 var datamanage = new DataManage(); 182 lock (syncState) 183 { 184 // コピーなど 185 } 186 return datamanage; 187 } 188 } 189 190 4、そもそもの項目オブジェクトを保証できるようにしておく 191 public class DataManage 192 { 193 public class State1 194 { 195 private object syncState = new object(); 196 private int a { get; set; } 197 private int b { get; set; } 198 199 public int A 200 { 201 get { lock (syncState) return a; } 202 set { lock (syncState) a = value; } 203 } 204 public int B 205 { 206 get { lock (syncState) return b; } 207 set { lock (syncState) b = value; } 208 } 209 210 public State1 Clone() 211 { 212 var ret = new State1(); 213 lock (syncState) 214 { 215 // ここでこぴーなど 216 } 217 return ret; 218 } 219 220 public void Copy(State1 state) 221 { 222 // ここでこぴーなど 223 } 224 } 225 226 public class State2 227 { 228 private object syncState = new object(); 229 private int c { get; set; } 230 private int d { get; set; } 231 232 public int C 233 { 234 get { lock (syncState) return c; } 235 set { lock (syncState) c = value; } 236 } 237 public int D 238 { 239 get { lock (syncState) return d; } 240 set { lock (syncState) d = value; } 241 } 242 243 public State2 Clone() 244 { 245 var ret = new State2(); 246 lock (syncState) 247 { 248 // ここでこぴーなど 249 } 250 return ret; 251 } 252 253 public void Copy( State2 state ) 254 { 255 // ここでこぴーなど 256 } 257 } 258 private State1 state1 = new State1(); 259 private State2 state2 = new State2(); 260 261 public State1 State1 => state1; 262 public State2 State2 => state2; 263 }
考え
1、値の保証はできるが、プロパティとして個々の変数にアクセスすることができず、
個々の値が欲しいのに、状態全体を取得しないといけない。
2、一番ましなように思えます。
3、保証はされているが、State1/State2としてかたまりで取得できない。
4、値を保証するといった観点では目標を達成しているが、オブジェクトをDataManageからローカルにコピーして使用する場合一つのスレッドからしか読み書きが行われないので、保証する必要がないのでなしかなと。
### 聞きたいこと
複数のスレッドから書き込み/読み込みが行われる想定の値を保持したクラスをどのように作成したらよいかです。
他にもいい方法や指摘などがあればよろしくお願いいたします。
回答2件
あなたの回答
tips
プレビュー