.NETで順番を守って排他制御

マルチスレッド環境で排他制御する時に、先に要求したスレッドほど先に実行させたい、ということを考える機会がありました。

.NETプログラミングで有名な排他制御方法はMonitorLinkManualResetEventLink でしょうか。C#ではMonitorクラスを便利に使えるlockステートメントもあり、私もよく使います。しかしManualResetEventは単一もしくは複数のスレッドを待たせて一気にスタートさせるものですし、Monitorは待ち状態にある複数のスレッドに対してロックを順番に与えてはくれません。後者はどういうことかというと、
  • スレッド1は既に排他ロックを取得し実行中
  • スレッド2がロックを求めて待ち状態に入った
  • スレッド2より後にスレッド3がロックを求めて待ち状態に入った
という状態でスレッド1がロックを開放した場合、次に排他ロックを取得するのは…どちらか分かりません。待ちスレッドが1個や2個では発生しにくいかもしれませんが、10や20スレッド待たせると順番通りにロックさせてくれないのが分かると思います。

最初に目をつけたのがQueueLink ジェネリッククラス。

using System.Collections.Generic;
using System.Threading;

class FIFOLock
{
  Queue<ManualResetEvent> eventQueue = new Queue<ManualResetEvent>();

  public void GetLock()
  {
    ManualResetEvent myEvent = new ManualResetEvent(false);
    lock(eventQueue)
    {
      eventQueue.Enqueue(myEvent);
      if(myEvent.Equals(eventQueue.Peek())) return;  // No thread is locking resource
    }
    myEvent.WaitOne();
  }


  public void ReleaseLock()
  {
    lock{eventQueue)
    {
      eventQueue.Dequeue();  // Remove ManualResetEvent of this thread
      eventQueue.Peek().Set();  // Signal to next waiting thread
    }
  }
}

実際にVisualStudioに打ち込んでないので、文法間違いなどあるかもしれません。打ち込まなかったのは考えている途中で「あ、lock使ってるからダメだ、これは」と思ったから。複数のスレッドがGetLock()に飛び込んできて競合待ち状態になったときに、次にeventQueueにアクセスできるスレッドが不定なため、順番の追い越しが発生する可能性があります。eventQueueがロックされている時間は僅かで、複数のスレッドがGetLock内で競合する確率は低いとはいえ、完璧ではない。ちなみに.NET 4.0ではConcurrentQueueLink なんていうスレッドセーフなQueueが登場したので、使えるかもしれません。

次にInterlockedLink クラスを使うこと。Incrementメソッドを使えば確実に早くやってきたスレッドから小さい番号を割り当てることができます。しかし単に数字が分かっただけ。各スレッドに自分の順番が来るまで待たせる上手い方法が分かりません。唯一思いついたのが、もう一個Interlockedで管理される整数を用意して、処理が終わったスレッドはこの数を増やしていくこと。銀行とかにある順番待ち整理券がイメージしやすいでしょうか。前者の変数が整理券の番号で、後者が「○番のカードをお持ちの方…」としゃべる機械。自分の番号が来たスレッドは処理を開始。

ただこの方法は各スレッドが自分の順番が来たかどうかポーリングでチェックせねばならず、CPU負荷が高くなる欠点があります。負荷の低いManualResetEventなどを使いたいのですが、Interlocked.Incrementで得られた数字とManualResetEventを結び付けようとする(Dictionary<int, ManualResetEvent>とか)所でスレッドセーフにする方法が思いつかず。

現時点の答えはReaderWriterLockLink を使い、全スレッドAcquireWriterLockを呼び出すこと。とりあえず100スレッドAcquireWriterLockを呼び出して待ち状態に入るプログラムを書いてみましたが、順番通りにスレッドがロックを取得していました。こういう使い方って、保障されているのでしょうか? ちなみにReaderLockされている状態ではAcquireWriterLockは待ち状態にされますが、その後にAcquireReaderLockのスレッドが来ると待ち状態のAcquireWriterLockを平気で追い抜きます(複数同時ReaderLockを認めているから)。

[2011/8/2 追記] 最終文訂正(AcquireReaderLock→AcquireWriterLock)

— posted by mu at 09:44 pm   commentComment [0]  pingTrackBack [0]

30VでLED

blog20100721-ConstantCurrentCircuit

先日の記事Link で触れた回路設計の見直しに関連するのですが、詳しい背景は省略して要求事項を要約すると、
  1. 外部から来る電圧のOn/Offに合わせて普通のLEDを点滅させる。
  2. その電圧は10~30V。外部で使用する電源電圧なので電源を変えない限りは一定。
  3. この電圧以外にLEDが使える電力源はない。
まずこの電圧を普通のLEDに直接入れると確実に焼けてしまいます(5Vでも煙出せますよ)ので、電圧を落とさないといけない。一番簡単なのは直列に抵抗を入れることですが、電源電圧の変動幅が大きいので全電圧に対応できる抵抗値が決まらない。電源がOn/Offを繰り返すのでレギュレータやDC-DC変換回路もダメ。

ここまで電圧電圧と書きましたが、LED制御に重要なのは電流量で電流を決めればLEDにかける電圧が決まるというのが正しい考え方。というわけで、LEDに20mAを流す定電流回路を考えればいいことになります。もっとも簡単なのは定電流ダイオードLink という素子を使うことですが、その場合問題になるのが発熱。

(動力・音・光などを発生しない)回路に電圧をかけて電流を流すと必ずジュール熱Link が発生します。今回の場合なら30V×20mA=0.6W。どこかで必ず発生します。LEDに直接繋ぐと焦げてしまうのはこの熱がすべてLEDで発生するため(実際にはもっと大量の電流が流れもっと発熱します)。抵抗器や定電流ダイオードを直列に繋ぐと、発熱がLEDとで分担されるのでLEDが焼けずにすむわけです。

で、一般的な定電流ダイオードが許容できる発熱量は0.3Wが多いので、完全にオーバー。写真上側のように複数を並列に繋いで発熱を分担させないといけません。こんな米粒みたいな素子がよく0.3Wも耐えられるなと思ったら、リード線を伝わって基板などに放熱させることを前提としているようですね。写真の縦に取り付けてある銅版は放熱目的だったりします。

blog20100721-ConstantCurrentCircuit

別の解決としてはトランジスタを使った定電流回路Link 。発熱はトランジスタ・エミッタに接続された抵抗器・LEDで分担されます。一番発熱するのはトランジスタなのですが、トランジスタは種類が豊富、安くて発熱に強い(コレクタ損失が大きい)やつが一杯あるのが魅力。

しかし…定電流ダイオード3個と比べると、トランジスタを使った回路はユニバーサル基板上では倍の面積を取るんですよね。今回基板面積にもあまり余裕がないので、素直に定電流ダイオードでしょうか(だけど値段高い)。

[参考] 個別半導体の豆知識 (なひたふ電子情報)Link

— posted by mu at 10:39 pm   commentComment [0]  pingTrackBack [0]

PCでmsec時間測定(5) - 校正

AVR側はとりあえずできLink 、Windows側も結構出来上がってきました。センサとの接続部で回路設計の見直しが生じ、プログラムの方は待ち状態になりつつあるため、以前から気になっていた以下のことを検証することに。
正確な時間を測定しているのか
AVRを駆動するクロックをカウントして時間を測定しているので、正確さはクロックのそれに直接依存してます。ストロベリーリナックスLink のボードは16MHzクォーツですのでそれほど狂ってはいないと思いますが。
頻繁にボタン・センサをOn/Offしても正確に測定できるか
回路はOn/Offが切り替わったときだけPC側にその情報を送ります。On/Offが頻繁に起きるとUSB通信も増えるわけで、そういったCPU負荷が高い状態でも時間を正確に刻めるか。
というわけでPC側のプログラムを拡張。
  • PCの時計は信用できないので、あらかじめNTPLink でサーバに同期。
  • AVR側は10kHz(1秒間に1万回)、内部のカウンタを延々と+1し続けます。PCから命令を受けるとその時の内部カウンタをPC側に返す機能を追加。
  • PC上のWindowsプログラムは1時間ごとにAVR側に内部カウンタを報告させるコマンドを発行、1時間の間にカウンタがいくつ増加しているかを調べる。
  • 上の測定をスイッチのOn/Off無しと頻繁に繰り返す状態で行い、比較する。
On/Offの繰り返しは手元にあったPIC 12F683でM系列Link を発生させるプログラムを作成、AVR側のスイッチ入力としました。AVRのクロックが正確なら、1時間後のカウンタは3600万増えているはず。測定の結果は以下の通り。
スイッチOn/Off 1時間のカウント増加 1秒あたり
なし 35998815.95 9999.67
あり 35998770.97 9999.66

今やっているのはミリ秒単位の測定なので、1秒間1万カウント中影響が出てくるのは10の位。しかしAVR側のカウンタの狂いはその2桁下、スイッチOn/Off有無による違いは更に1桁下。

スイッチOn/Off間隔が数分にも及ぶような測定の場合はミリ秒単位に影響が出てくるのでこの結果による補正が必要になってきますが、今前提としているのは1~2秒間隔。無視しても良さそうですねぇ。

[2010/9/25 追記] 続きLink

— posted by mu at 07:11 pm   commentComment [0]  pingTrackBack [0]

今から投票行ってきます

この2週間ゲームしながら政見放送見てたりしたのですが、結局いつもと同じくあまり考えずに投票してたりします。大体この地区の候補者も知らないしorz 今回は小党乱立で、さらに分かんね。

ただひとつ思うのは
減税だってバラ撒きでしょ?
撒く方向が違うだけ。なにバラ撒き批判しておいて減税(もしくは税率維持)謳ってるんだか。公約をカタカナに言い換えたり、言葉遊びが過ぎる。

[2010/7/11 追記] 完了。初めて出口調査ってやつを経験。

— posted by mu at 03:13 pm   commentComment [0]  pingTrackBack [0]

らっきー☆れーさーの景品来た

blog20100710-HaruhiMoviePop

映画「涼宮ハルヒの消失」のPOP(立て看板)。らっきー☆れーさーLink 第1期の景品。来るとは思わなかった。近くで見るとすごい解像度低い(ドット数の少ないCGを無理に引き伸ばしてある)のですがorz

らっきー☆れーさーというのは、2010年4月から毎週計10回放送されたらき☆すたスピンアウト企画。個人的には以下に書くように失敗感漂う感じで終わったのですが、これ書くためにHP見直したら予想外の第2期開始w

第1期のルールはうろ覚えですが、
  • カートで勝負、1位になった人だけその人が推す商品を広告できる。
  • 番組パーソナリティである白石稔さんが勝ったときは京都アニメーションLink の商品宣伝。
  • 声優ほかアニメ関係のゲスト参戦もあるよ!
という感じ。私の興味はゲスト参戦者。今野宏美さん(小神あきら役)は出るのだろうか、でも彼女運動神経鈍いらしいしなぁ、とか思いつつ第1回の参戦者をみて拍子抜け。

白石稔以外は京アニスタッフしかいねぇ

これ誰が勝っても京アニ商品の宣伝じゃないか。オープニングが「第1回目から雨!」で始まったので、「雨女の今野さん来たのか!?」と期待したのにねぇorz 第2レースも同じレース場ってことは同じメンバーで2回撮り。なんだかなぁ。

そんな感じで固定メンバーで回を重ね、毎回京アニ商品の宣伝。レースの意味が感じられない状態でした。う~ん、広告希望者がいないのだろうか。

広告主が付きゲスト参戦者が現れれば状態が変わるかなと思っていた中、第5回に水原薫さん(日下部みさお役)がゲスト参戦。お、これで状況が変わるかなと思ったのですが、逆に現在のルールの欠陥に気づかされました。
ハンデを貰っても水原さん完敗
レギュラー陣、過去数回のレースで上達してまして、初心者の水原さん歯が立たず。アニメ関係者でカートが上手いなんて人、かなり敷居高いでしょう。ゲストを立てて勝たせようものなら出来レースにも取られかねないわけで、ゲストが商品紹介する機会は高くない。
1位にならないと宣伝できない
宣伝してもらえない確率が高いなら、広告主も手が出しにくくないかなと。類似した企画の熱湯コマーシャルLink は時間の違いはあれど宣伝はできたわけで、まったく宣伝できないでは旨みが無い。無料で宣伝させてくれるならまだ挑戦する気になるかもしれないけど、新感覚の「商品紹介番組」なわけでして、広告費取るだろ?

ちなみに次のレースで水原さん勝ちましたが、京アニ商品の宣伝でしたorz

苦境に立たされた番組には付き物のマイナーチェンジを繰り返しながら回を重ね、たどり着いたのは、
  • F1よろしく順位に応じてポイントをレーサーに付与、累計ポイントを争う形式。事実上のゲスト参戦者廃止ですね。
  • さらに視聴者にある時点での累計ポイント順位クイズを提供、正解者にはプレゼント。
という内容でした。

で。直前まで気づかなかった私も馬鹿ですが、応募締め切りが全レース終了後だったんですね。しかもご丁寧にWeb上では毎レースの結果と累計ポイントを掲載。ほとんどヒントとして下に答えが書いてある懸賞クイズの状態w さすがにこんなクイズ、当選者5名だし当選は期待できないと思いつつ応募したら、当たってしまったというお話でした。運がよかったのか応募者が少なかったのか、悩むところ。

私の考えていた番組の欠点がある程度は当たっていたのか、2010年7月から始まった第2期は順位に応じて秒数が違うながらも全商品紹介など修正がされてきたようです。ただ疑っちゃキリ無いんだけど、最初から各商品の秒数決まっててレース後に誰が何を紹介するか割り当てても分からないんだよねぇ。どうせなら、各レーサーに広告主を結び付けておいて「毎回紹介時間が短いって怒られた」とか内情暴露ネタ入れたほうが面白いかなと思ったり。 商品紹介とポイント争奪戦のレースを分けた(2レース開催)ようです。というわけで、動画配信のある商品紹介レースは(凶悪なハンデなど)脚色OK、ゲストカモ~ンですね。

ちなみに第2期も同様のクイズがありまして、締め切りは全レース終了後です☆

— posted by mu at 11:11 am   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0222 sec.
prev
2025.7
next
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31