すいません、VB4しかやってないんです、VBAはやったけど(ぼそ) チラシの裏だって立派な書き込み空間なんだからねっ!資源の有効活用なんだからねっ!とか偉そうに言ってるけど、実は色々と書き残したいだけ

だからなに? どうしろと? くるみサイズの脳みそしかないあやしいジャンガリアンベムスターがさすらう贖罪蹂躙(ゴシックペナルティ)

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  632  : 記事  35  : コメント  11677  : トラックバック  143

ニュース


片桐 継 は
こんなやつ

かたぎり つぐ ってよむの

大阪生まれ河内育ちなんだけど
関東に住みついちゃったの
和装着付師だったりするの
エセモノカキやってたりするの
VBが得意だったりするの
SQL文が大好きだったりするの
囲碁修行中だったりするの
ボトゲ好きだったりするの
F#かわいいよF#

正体は会った人だけ知ってるの

空気読まなくてごめんなさいなの


わんくまリンク

C#, VB.NET 掲示板
C# VB.NET掲示板

わんくま同盟
わんくま同盟Blog


WindowsでGo言語
WindowsでGo言語


ネット活動


SNSは疲れました

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

イベント活動

プログラムの活動

やまたのおろちが酒飲んでます。あいかわらずの飲兵衛です。

その1

http://blogs.wankuma.com/esten/archive/2008/12/03/162607.aspx

ここでは、ただ首一本がガブガブ飲むだけだったんだけど、それじゃ他の首が飲ませろとうるさいので、全部の首がせーのっ!で飲めるようにして

その2

http://blogs.wankuma.com/esten/archive/2008/12/09/163043.aspx

となったわけだけれども、コメントでツッコミがあったように、これだけでは全く持って、ダメダメプログラミングなわけですw。はい、わざとです。

では、どうしようか? リファクタする?

でもその前に、まだやっておかなくちゃいけないことがあるんだわ。

やまたのおろちが飲みたい酒ツボが1つだったときにどうなるかって話。

Imports System
Imports System.Threading

Module OrochMTA

    Delegate Sub DrinkingSAKE()

    '酒ツボは一つ
    Private sakeTubo As Integer

    '酒ツボの残り
    Private sakeNokori As Integer

    <MTAThread()> _
  Public Sub Main()

    '酒ツボに酒を準備
    sakeTubo = 50000
    sakeNokori = sakeTubo

    '本体で首が別々に酒飲みするのを身構える

        Dim ts As New ThreadStart(AddressOf OrochiDrinking)

        Dim workerThread As New Thread(ts)

        workerThread.SetApartmentState(ApartmentState.MTA)

        workerThread.Start()

        workerThread.Join()

        Stop

  End Sub

    Private Sub OrochiDrinking()

        'まずは首を八本で飲んでみる
        Dim headCount As Integer = 8

        '酔っ払い待ち行列を首の数だけ準備
        Dim yoppa(headCount - 1) As WaitHandle

        For i As Integer = 1 To headCount

            '飲んだ首から酔っ払いへと
            yoppa(i - 1) = HeadDrinking(i).AsyncWaitHandle

        Next

        '全部の首が酔っ払いになるまで待機
        WaitHandle.WaitAll(yoppa)

    End Sub

    Private Function HeadDrinking(ByVal headNo As Integer) As IAsyncResult

        '指定した番号の首に酒を飲ませる
        Dim myHead As New OrochiHead(headNo)

        Dim gubi As New DrinkingSAKE(AddressOf myHead.Drink)

        '酒飲み開始とともに、酔っ払い待ち行列へ戻す
        Return gubi.BeginInvoke(Nothing, Nothing)

    End Function

    'おろちの首をクラス化
Private Class OrochiHead

    Private meNumber As Integer

    '何番目の首なのかを保存
    Public Sub New(ByVal headNo As Integer)

        meNumber = headNo

    End Sub

    '酒を飲むメソッド
    Public Sub Drink()

        Dim sakeZuki As New Thread( _
          New ThreadStart(AddressOf DrinkSAKE)) ' 

        sakeZuki.Start()
        sakeZuki.Join()

          Console.WriteLine("ぷはーっ! {0}番目の首、飲み終わり!", meNumber)

    End Sub


  ' 酒のみスレッド
  Private Sub DrinkSAKE()

        Dim totalDrunk As Integer = 0
        Dim nowDrink As Integer

        Dim oneDrink As New Random
        Dim oneBreath As New Random

        '酒ツボの中の酒を飲み干す
        While (sakeNokori > 0)

            '一回飲むたびに息継ぎ
            Thread.Sleep(oneBreath.Next(30, 60))

            '一回ぐび
            nowDrink = oneDrink.Next(1, 100)

            '全部でどれくらい飲んだ?
            sakeNokori -= nowDrink

            Console.WriteLine("{0}番目の首が {1} リットル ぐびっ : 残り {2} リットル", meNumber, nowDrink, sakeNokori)


        End While

  End Sub

End Class

End Module

ぱっと見、これだけに見えるよね?

でも、これが落とし穴。

image

CPUの数が多い時、スレッドはどのCPUで管理されるかはOS次第。でもそのバラバラに動いているスレッドの処理が一箇所のアドレスにある値を読み出して書き出すわけだから、「今ある酒の量が本当に正しい」かどうか判らなくなる。これが小さなスレッドと一瞬で終わるプログラムなら気がつかないかもしれない。でも、沢山のCPU、スレッドで動いたときこの落とし穴ははっきりと結果にでてくるんだよね。

つまり、一つの酒ツボから複数の首が酒を飲むわけだけど、実際に、首の動きを制御しているのは、CPU。だから、CPUが複数あると、本当の意味で「同時に」首が酒を飲むことができるわけで、そうなると、酒ツボから飲んだ→残りこんだけ、という動きも本当の意味で「同時に」起きちゃうことになるの。そうなっちゃうと、今の酒の残り、は本当に正しい!ということがこのままだといえなくなっちゃうんだ。たとえば残り100リットルから、ある首Aが20リットル飲んで、ある首Bが10リットル飲んだ。この時、本当だったら残りは70リットルのはずなんだけど、2個のCPUがあるときに、Aの「100-20」の計算を1CPU、Bの「100-10」の計算を1CPUがそれぞれに同時にしちゃったら結果は「80」もしくは「90」として格納、これ、プログラム的には正しい動作なんだもの。見えないだけで、実はやまたのおろちの首はおもいっきり絡まってて、絡まったなりに酒を飲んだツモリになってたりしてるってことだよね。

厄介なのは、これ、必ず再現できると限らないんだ。

VisualStudioのデバッガをつかってブレークポイントを仕掛けて止めただけでも、マルチスレッドプログラミングは直列の処理に最適化されてしまうので、ステップするとうまくいっちゃったりとかする。「なんで?何が悪いの?」がさっぱり判らなくなっちゃう。

おそろしいよね、それって。

だから、スレッド間でやり取りする値、読み出したり書き出したり更新したりする時には、必ずスレッド間で同期を取れるように作ってあげないといけない。

マルチスレッドが難しいのはこの考え方があるからで、実はこれを回避するための処理クラスやステートメントが、ちゃんと用意されてたりするのね。

それが、InerLockedクラス、そして、SyncLockステートメントブロック

じゃ、こいつらを使って、やまたのおろちに行儀良くお酒を飲んでもらおうと思う。ついでに、リファクタってやつもやってみるってことで、それは次回ねw

実はまだ出てない新キャラがいるんだ、スサノオってのがwww

投稿日時 : 2008年12月27日 21:27

コメント

# re: やまたのおろちが酒を飲む~片桐的VB.NETスレッドプログラミング~その3 2008/12/28 1:37 通りすがり
CPUが必ず1個だとだいじょうぶでしょうか?


# re: やまたのおろちが酒を飲む~片桐的VB.NETスレッドプログラミング~その3 2008/12/28 19:46 かたぎり
必ず大丈夫ってのは絶対に言えないと思う
ただ、現象が出にくいってだけだから

同期オブジェクト使用推奨しますですよ

# re: やまたのおろちが酒を飲む~片桐的VB.NETスレッドプログラミング~その3 2008/12/28 22:00 通りすがり
えと、CPUが複数だから同時に動くからおかしくなるんですよね?
(という風に読み取ったんですが、そういうことじゃなかったです?)
1個でも同時に動くんでしょうか??


# re: やまたのおろちが酒を飲む~片桐的VB.NETスレッドプログラミング~その3 2008/12/29 9:52 かたぎり
一個でも「同時に」動くかもしれないし、うごかないかもしれない。
スレッドが難しいのは、どう動くか、の完全な制御はその時のCPUとメモリ状態と他のプロセス状態によって左右されるのでコントロールできない(難しい)ってところ。
だから、絶対ないよ、といえないし、絶対あるよ、ともいえないの。

だから、同期オブジェクトなりブロックなりを使用して動作の保障というか担保を取るって考え方の方がいいと思うですよ

# re: やまたのおろちが酒を飲む~片桐的VB.NETスレッドプログラミング~その3 2008/12/29 17:48 通りすがり
CPU1個でもどうやら駄目らしいということで、それは分かりました。

その上で再度ちょっと疑問なんですけれど、例えば
>2個のCPUがあるときに、Aの「100-20」の計算を1CPU、Bの「100-10」の計算を1CPUがそれぞれに同時にしちゃったら結果は「80」もしくは「90」として格納、これ、プログラム的には正しい動作なんだもの。
のように書かれてるんですけれど、CPU1個でも同時に動くというのは、どうやって動くんでしょうか?
この辺を見て、CPUが複数あるから同時に動くのだと仰ってるのだと思ってました。


# HgkTMNFJMJNUIz 2014/07/19 3:14 http://crorkz.com/
TB9AJt I really liked your article post.Really looking forward to read more. Fantastic.

# dRLbuUecNKD 2014/08/28 7:56 http://crorkz.com/
5N0FB9 I simply could not go away your website prior to suggesting that I extremely loved the standard info a person provide on your guests? Is going to be again incessantly to inspect new posts

# ZrRjvaQXWnPF 2014/08/30 21:22 http://facebook.com/pages/Flyttfirma-i-Stockholm/5
you will have an important weblog here! would you prefer to make some invite posts on my blog?

# kCjWOIkNBdwjaIxVSsc 2014/09/09 12:41 http://vente-sur-internet.com/luis-souto/
Good write-up, I am normal visitor of one's site, maintain up the excellent operate, and It is going to be a regular visitor for a lengthy time.

# IgvRcEDaIRqmEAtTdsC 2014/09/11 20:41 http://www.ukessays.com
It's exhausting to seek out knowledgeable folks on this subject, however you sound like you recognize what you're talking about! Thanks

# ロレックスコピー 2023/05/12 19:51 coxAcquic
ブランド腕時計バッグ財布コピー エルメス(バッグ、時計) シャネル(バッグ、時計)ルイヴィトン(バッグ、時計) ブルガリ時計 グッチ(バッグ、小物) ロレック(時計)オメガ(時計) IWC(時計)FRANCK MULLER(時計)1.最も合理的な価格で商品を消費者に提供致します。2.弊社の商品品数大目で、商品は安めです!商品現物写真。3.数量制限無し、一個の注文も、OKです。4.1個も1万個も問わず、誠心誠意対応します。5.不良品の場合、弊社が無償で交換します。不明点、疑問点等があれば、ご遠慮なく言って下さい。}}}}}}
https://www.bagssjp.com/ems/detail-44.html
https://www.bagssjp.com/product/detail-1629.html
https://www.bagssjp.com/product/detail-137.html
https://www.bagssjp.com/product/detail-8291.html
https://www.bagssjp.com/menu/menu_pinpai-4-68.html


Post Feedback

タイトル
名前
Url:
コメント