Hatena::ブログ(Diary)

はけの徒然日記 このページをアンテナに追加 RSSフィード

2005 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 04 | 05 | 08 | 09 | 10 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 |
2011 | 01 | 02 | 03 | 04 | 11 | 12 |
2012 | 02 | 03 | 05 |
2014 | 02 | 03 | 04 | 05 | 12 |
2015 | 05 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 04 | 05 | 08 | 09 | 11 | 12 |
2017 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 |

2005-07-20(Wed)

並行処理 その3

Ruby勉強

スレッド間の同期の実験、下のプログラムボタン1に関連付けられているメソッドは2つのスレッドが並行して実行される。一つは変数@xを+1、変数@yを−1する処理。もう一方は@xと@yの合計を表示する処理である。前者のスレッドで変数@xと@yの値を変化させているが合計すれば常に200になるはずである。

しかしボタン1を押すと200以外の数値になりエラーとなる場合がある。これは後者のメソッドによる2つの変数の値の読み取りが、ちょうど@x=@x+1を実行し、かつ、@y=@y-1が実行されていないタイミングで為されるためである。(このプログラムではエラー頻度を上げる為に前者のスレッドにsleepを挿入している)

このようなことが発生しないようにするには、一方のスレッドが変数をアクセスする間、他方のスレッドによる変数アクセスロックすればよい(はず)具体的には、Mutexクラスインスタンス@aを作成して、各スレッドが変数をアクセスする部分をsynchronizeメソッドで囲む。

@a = Mutex.new

@a.synchronize {……}

こうすることでエラーの発生が無くなる。

@zをローカル変数ではなくインスタンス変数にしたのは、@a.synchronizeの{}でひとつの変数のスコープが形成されて外部から参照できなくなる為。

#!/usr/bin/env ruby

require "qte"
require "qpe"
require "thread"
include Qte
include Qpe


class SampleWindow < QMainWindow
   def initialize()
      super()
      setCaption(tr("サンプル"))
      @msg = QLabel.new(tr("これはサンプルプログラム"),self)
      @msg.setGeometry(10,10,300,30)


      @ebox1 = QMultiLineEdit.new(self)
      @ebox1.setGeometry(0,100,635,300)
      @ebox1.setReadOnly(true)

      @pb1 = QPushButton.new(tr("ボタン1"),self)
      @pb1.setGeometry(300,5,100,30)
      connect(@pb1,QSIGNAL("clicked()"), self, 'cnt')

#      @a = Mutex.new
      @x = 100
      @y = 100
      @z = nil
   end

   def cnt
      @ebox1.clear
      @x = 100
      @y = 100

      Thread.new do           #スレッド1
         Thread.pass
         100.times do |i|
#            @a.synchronize {
                @x = @x + 1
                sleep 0.1     #エラー発生頻度を上げる為
                @y = @y - 1
#            }
         end
      end

      100.times do            #スレッド2
#          @a.synchronize {
             @z = @x + @y
#          }
             @ebox1.insertLine(@z.to_s)
             if @z != 200 then
                @ebox1.insertLine("!!!Error!!!")
             end
      end
   end
end

$defaultCodec = QTextCodec.codecForName("utf8")
app = QPEApplication.new([$0]+ARGV)
app.setDefaultCodec($defaultCodec)
QApplication.setFont(QFont.new("lcfont",18))
app.showMainWidget(SampleWindow.new)
app.exec

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/hake/20050720/p2