go は同時実行プログラム言語であるためchannel
(ほとんどすべてのコードで使用しています)、または他のものを synchronous に使用しgoroutine
ます。
また、スケジューラを使用してスケジュールを設定することも知っていました。つまり、各ゴルーチンで (チャネル アクション、runtime.goSche など) を呼び出して、それが実行されることを保証する必要がありますgoroutine
。scheduler
上記は私の現在の制限事項であり、go
それらを使用してコードを設計しています。
しかし、コードでコードブロッキングが発生することもわかりました。また、ブロックの原因を見つけるのは困難です ( GDBを使用しても)。
私は何かを見逃していましたか?
ブロックの原因として他に何が考えられるでしょうか?
また、注意すべきことは何ですか?
[編集] : 私のプロジェクトのコードは少し大きいので、OK。標準 コードは表示せずgo
、コード ブロッキングの原因となる可能性のある部分の一般的な考え方だけを示します。私のプロジェクトのファイル送信モジュールのコードの一部を次に示します。
func(c *client)listenRead() {
for {
_ := websocket.JSON.Receive(c.ws, &package)
switch package.Op {
case fileUpld:
c.fileMan.store <- package.Body
case fileDownld:
c.fileMan.downld <- package.Body
case c.xxx:
...
default:
// bad package.
}
}
}
クライアントは、別のクライアントから websocket を介してメッセージをリッスンして受信し、のpackage
フィールドOp
に従ってパッケージを別のhandlerに転送します。たとえば、以下にfileManager
示します。
func(fm *fileManager) fileRouter() {
for {
select {
case fs := <-fm.fileUpld:
if window < filesize {
f.Write(fs.content) // client A write to file
window += fs.contSize
} else {
f.close() // close file
}
case fd := fm.downld:
go fm.downldFile(fd)
}
}
}
から送信されたデータをchanfileManger
が取得すると、 はファイルの断片を受信してサーバーに保存できます。また、クライアントから を受信するとファイルをダウンロードでき、以下に示すジョブを実行するために を生成します。 fileUpld
client
request
goroutine
func(fm *fileManager) downldFile(fd) {
f := getFile(fd) // get the file that client A write
b := make([]byte, SeqLength)
for {
if convergence < window {
f.Read(b)
// wrap 'b' to package 'p', for send
fm.server.send <- p // send to client B
} else if window < fileSize {
runtime.Goshed()
} else {
// download done.
fm.done <- xx
return
}
}
}
私のファイル送信モジュールの主なアイデアは、クライアントAがクライアント B にファイルを送信し、クライアントBacceptance
からのファイルを待ちたくないということです。つまり、最初にサーバーに保存し、クライアント Bが後でファイルを取得します。サーバーからダウンロードします。ただし、クライアント Aがファイルをアップロードしている間に、クライアント Bがファイルをダウンロードする可能性があります。したがって、アップロードとダウンロードの間に同期が必要です。
これを実装するために、 window、convergence、filesizeの3 つの変数を使用します。クライアントAがファイルをアップロード(書き込み)すると、ウィンドウは書き込みバイトの値を増やします。クライアント Bがファイルをダウンロード (読み取り) すると、コンバージェンスによって読み取りバイト数が増加します。のみ発生する間のみ発生します。と同じように:Write
window < filesize
read
convergence < window
+-----------+---------------+--------------+
|############|||||||||||||||| |
+-----------+---------------+--------------+
^ ^ ^
| | |
convergence window filesize
これによりデータ競合が発生することはわかっていましたが、まだ書き込まれていないread
コンテンツを読み取らないことも保証されます.(ところで:それを実装するために使用するソリューションはありません.)write
channel
アップロードとダウンロードを同時に行おうとすると、コードブロッキングが発生します(クライアントAを遅くして達成します)。しかし、2に設定すると問題ありませんGOMAXPROCS
。