すいません、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は疲れました

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

イベント活動

プログラムの活動

帰ってきたヤマタノオロチw

本体一つに8つの首があるやまたのおろちさんが、一つの酒ツボから酒をグビグビとマルチスレッドに飲んでるプログラミングのお話ね。

まじめにマルチスレッドについてMSDN読んでたら、ふと、こんなページを発見。

ReaderWriterLockSlim クラス (System.Threading)

これは便利そう。マルチスレッドでプログラミングして何が大変って、変数の同期と排他だと思ってるから、それをまとめて簡単に処理させてくれるならとっても素敵。

というわけで、リベンジしたリファクタソース

Imports System
Imports System.Threading

Module OrochMTA

    Delegate Sub DrinkingSAKE()

    '酒ツボに酒を準備 
    Public inSakeTubo As New SakeTubo(40000)

     _
    Public Sub Main()

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

        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


    Public Class OrochiHead
        'おろちの首クラス   

        'お前は何番目なのかを保持
        Private meNumber As Integer

        '何番目の首?初期化w 
        Public Sub New(ByVal headNo As Integer)

            meNumber = headNo

        End Sub

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

            Dim nowDrink As Integer
            Dim nowNokori As Integer

            Dim oneDrink As New Random
            Dim oneBreath As New Random

            '酒ツボの中の酒を飲み干す   
            While Not (inSakeTubo.Nomihoshited)

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

                '酒つぼから飲んでみる
                If inSakeTubo.Nomihoshited Then
                    Console.WriteLine("{0}番目の首「もう酒がねぇよ!!ぷんすか」", meNumber)
                    Exit Sub
                Else
                    '一回ぐび   
                    nowDrink = oneDrink.Next(1, 100)
                    nowNokori = inSakeTubo.Nokori
                    inSakeTubo.Gubi(nowDrink)
                    If inSakeTubo.Nomihoshited Then
                        Console.WriteLine("{0}番目の首「ちきしょう!足りねぇよ!{1}のみてぇのに{2}しかねぇ!」", meNumber, nowDrink, nowNokori)
                        Exit Sub
                    Else
                        Console.WriteLine("{0}番目の首が {1} リットル ぐびっ : 残り {2} リットル", meNumber, nowDrink, inSakeTubo.Nokori)
                    End If
                End If


            End While

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

        End Sub

    End Class


    Public Class SakeTubo
        '酒つぼクラス
        'マルチスレッドでの読み書き保護処理を集約

        Private cacheLock As New ReaderWriterLockSlim()
        Private innerSake As Integer

        Public Sub New(ByVal litter As Integer)

            innerSake = litter

        End Sub

        Public Function Nokori() As Integer
            cacheLock.EnterReadLock()
            Try
                Return innerSake
            Finally
                cacheLock.ExitReadLock()
            End Try
        End Function

        Public Sub Gubi(ByVal gubigubi As Integer)

            Dim retFlag As Boolean = True

            cacheLock.EnterWriteLock()
            Try
                If innerSake > gubigubi Then
                    innerSake -= gubigubi
                Else
                    innerSake = 0
                End If
            Finally
                cacheLock.ExitWriteLock()
            End Try
        End Sub

        Public Sub Karappo()
            cacheLock.EnterWriteLock()
            Try
                innerSake = 0
            Finally
                cacheLock.ExitWriteLock()
            End Try
        End Sub

        Public Function Nomihoshited() As Boolean
            cacheLock.EnterReadLock()
            Try
                Return (innerSake.Equals(0))
            Finally
                cacheLock.ExitReadLock()
            End Try
        End Function

    End Class

End Module

長いorz

結果はこんな感じ。

image

あ、ちなみに、実行したマシンのCPUは せんとりーの♪せんとりーの♪せんとりーーーーのー♪マルチスレッドしてるーのー♪

シングルCPUではあるけれど、酒つぼクラスにちゃんと排他ロジックいれてないとうまく動かない。

あくまでも実験則なんだけれど、CPUの種類と数に依存するわけでなく、マルチスレッドという手法でプログラムを走らせてしまう時点で、それぞれのスレッドが参照する特定アドレスの中身が一律に保証されるためには排他が必須ってことだけは理解。こまけぇことはいいんだよ<違っ

image

図にするとこん感じ。酒つぼは1クラスにして、その中で読み書きの排他を実現しておいて、おろちの首クラスからは何も気にしないで変数を読み書きしてもらう仕組み。

並行してできることは、どんどん並行してもらっていいんじゃないかなと思っているので、大量データの処理なんかには有効なんじゃないかしら?実現したいことが「並行でできるのかどうか」を見極めるのは難しい部分はあるかもだけどね。

このソースを基準に、今度はスサノオさんに登場してもらおうと思ってます。例外処理ってやつねv

投稿日時 : 2010年3月13日 11:43

コメント

# re: やまたのおろちが酒をのむ・リターンズ~片桐的マルチスレッドVBプログラミング~ 2010/03/13 13:24 通りすがり
前から何度か指摘されてる気がしますが、
.NETでの普通のマルチスレッド処理にMTAは関係ありません。
STAだとWaitAllが使えないからというのは分かりますが、
それはそれだけの事であって、MTAにしないとマルチスレッド的に動かないということではありません。

話変わって、多分このコードだと自分が飲み干したという判定が正確ではないような気がします。
#携帯でコードがちゃんと読めてないので読み違いしてるかも知れませんが

まあ、これが正確である必要があるかは状況にもよりますが、
マルチスレッドプログラミングでは典型的なミスのひとつですので、
マルチスレッド絡みの話では一応触れておいた方がいいような気はします。


# re: やまたのおろちが酒をのむ・リターンズ~片桐的マルチスレッドVBプログラミング~ 2010/03/13 13:49 かたぎり
>とおりすがりさん

こんにちはです。
今までの通りすがりさんと同じ人かしらん?

MTAにしないとマルチスレッドではない、ということは言ってないのですけれど、そう読めていたらごめんなさい。
あくまでも、WaitAllが使いたいから、MTAを頭につけておりまするですよ

サンプルプログラムがきちんと動かないと話にならないと考えていますので、そこはね。

「自分が飲みほした」判定よりは「酒がもうないよ」判定に重視しちゃったところはあります。
自分が飲んで空にしたかどうか判定なら、違う書き方をしないときっとダメだと思っているので、読み違いではないですよ


# re: やまたのおろちが酒をのむ・リターンズ~片桐的マルチスレッドVBプログラミング~ 2010/03/13 18:50 通りすがり
本文でもMTAってワードが出ていたはずですが、なくなってますね。
せめて意味不明な指摘にならないように配慮して頂けたらと思います。

まあ、コードの方だけでも私はちょっと誤解を招く書き方だと思いますが。


# re: やまたのおろちが酒をのむ・リターンズ~片桐的マルチスレッドVBプログラミング~ 2010/03/13 19:07 かたぎり
>通りすがりさん

いろいろとごめんなさいです。
なにしろ脳味噌バッファ小さいので
配慮はどこまでできるかわからないけれど、
自身でできる限りの修正や訂正はしていくつもりです

お互い、いろんなことを知って歩み寄れたら、それがなによりですもの。
これからもよろしくです



# やまたのおろちが酒をのむ・リターンズその2~片桐的マルチスレッドVBプログラミング~ 2010/03/14 13:48 すいません、VB4しかやってないんです、VBAはやったけど(ぼそ)
やまたのおろちが酒をのむ・リターンズその2~片桐的マルチスレッドVBプログラミング~

# ANBlKQewCAaU 2011/12/17 19:38 http://www.neojogos.com
Hello! How do you feel about young composers?!...

Post Feedback

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