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が取得すると、 はファイルの断片を受信してサーバーに保存できます。また、クライアントから を受信するとファイルをダウンロードでき、以下に示すジョブを実行するために を生成します。 fileUpldclientrequestgoroutine
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がファイルをダウンロード (読み取り) すると、コンバージェンスによって読み取りバイト数が増加します。のみ発生する間のみ発生します。と同じように:Writewindow < filesizereadconvergence < window
+-----------+---------------+--------------+
|############||||||||||||||||              |
+-----------+---------------+--------------+
            ^               ^              ^
            |               |              |
       convergence        window        filesize
これによりデータ競合が発生することはわかっていましたが、まだ書き込まれていないreadコンテンツを読み取らないことも保証されます.(ところで:それを実装するために使用するソリューションはありません.)writechannel
アップロードとダウンロードを同時に行おうとすると、コードブロッキングが発生します(クライアントAを遅くして達成します)。しかし、2に設定すると問題ありませんGOMAXPROCS。