DOBON.NET DOBON.NETプログラミング掲示板過去ログ

複数スレッドでのEncodingの同時使用に関して

環境/言語:[.NET 1.1(VB2003)]
分類:[.NET]

Text.Encodingを使用して複数スレッドでS-JISでのString ⇔ Byte()の相互変換を行うプログラムを
作成しています。(String ⇒ Byte()、Byte() ⇒ Stringのどちらを行うスレッドも複数存在する)

S-JISのEndocingを取得する方法はいくつかあると思うのですが、
次のような簡単なコードで確認できるように、どうもどの方法で取得しても
同一のオブジェクトしか取得できないようです。
-----------------------------------------------------------------------------------------------------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim SJIS0 As Encoding = Encoding.Default
    Dim SJIS1 As Encoding = Encoding.GetEncoding("shift_jis")
    Dim SJIS2 As Encoding = Encoding.GetEncoding(932)

    If SJIS0 Is SJIS1 Then
        Console.WriteLine("SJIS0とSJIS1は同一のオブジェクトを参照しています。")
    End If
    If SJIS1 Is SJIS2 Then
        Console.WriteLine("SJIS1とSJIS2は同一のオブジェクトを参照しています。")
    End If
End Sub
-----------------------------------------------------------------------------------------------------------

ところで、String ⇒ Byte()にはGetBytesメソッドを使用し、Byte() ⇒ StringにはGetStringメソッドを
使用するわけですが、どちらのメソッドもインスタンスメソッドであり、またMSDNライブラリによると
インスタンスメソッドは「スレッド セーフであるとは限らない」とあります。

以上を総合すると、冒頭に書いたような用途にはEndocingは使用できないように思えるのですが、
どうなのでしょうか?

それとも、おなじエンコードを行う、異なるEncodingオブジェクトを作成する方法があるのでしょうか?

よろしくお願いします。
■No17975に返信(CRTさんの記事)

こんにちは エツです
全く自信はないですが、発言させて頂きます。
間違っていましたら、御指摘お願いします。

VB2005 Express Edition のヘルプには次のように書いてあります。

スレッド セーフ
この型の public static (Visual Basic では Shared) メンバはすべて、スレッド セーフです。インスタンス メンバの場合は、スレッド セーフであるとは限りません。

これの解釈ですが
Encoding.Default
Encoding.GetEncoding(...)
は共有メンバ = {public static (Visual Basic では Shared)} と考えると
スレッド セーフです。

CRTさんの解釈は

> Dim SJIS0 As Encoding = Encoding.Default
> Dim SJIS1 As Encoding = Encoding.GetEncoding("shift_jis")
> Dim SJIS2 As Encoding = Encoding.GetEncoding(932)

がインスタンスなので

> ところで、String ⇒ Byte()にはGetBytesメソッドを使用し、Byte() ⇒ StringにはGetStringメソッドを
> 使用するわけですが、どちらのメソッドもインスタンスメソッドであり、またMSDNライブラリによると
> インスタンスメソッドは「スレッド セーフであるとは限らない」とあります。
>

スレッド セーフであるとは限らない と解釈しているわけです。

全く自信はありませんが 私の解釈は間違っているのでしょうか?

#実際CRTさんがスレッド セーフでないことを確認済みなら私の解釈は間違っています。
#突っ込み大歓迎というかそれを期待して。

たぶん、GetBytesエントリとその中のローカルなものはスタックなので
そいつらはスレッドセーフではないかなと。
じゃぁ、その外の共有リソースとかくさいわけですが、Encodingテーブル?などががあったとしても
参照しかしてないと思うので(書き換えが起こるものが浮かばない)実質スレッドセーフでないのかなと思ったりする。
まぁ、憶測で済まされるもんではないんだけど。(汗
>エツさん
いえ、スレッドセーフ「ではない」、という確認がとれているわけではありません。
というより、むしろ今までの動作を観察する限り、実質的には問題ないようにも思えます。
ただ、問題がないならないで、その確証というか、理論的な裏づけが
欲しいなと思いまして・・・。


> Encoding.Default
> Encoding.GetEncoding(...)
> は共有メンバ = {public static (Visual Basic では Shared)} と考えると
> スレッド セーフです。

これはしかし、素直に考えれば上記のプロパティ・メソッドの動作がスレッドセーフである、
という意味であって、それによって取得されたインスタンスの
インスタンスメソッド(たとえばGetString)の動作のスレッドセーフまで
保障されるとは考えにくいのではないでしょうか?

というより、そもそも.NET 1.1ではこれらの共有メソッド呼び出しでしかEncodingの
インスタンスを取得できないようですから、エツさんの仮定が正しいとすると
MSDNライブラリにわざわざ「インスタンスのメンバの場合は、スレッドセーフであるとは限らない」
と表示する意味がなくなってしまいます。

もっとも、これはMSDNライブラリの書き手は不合理なことは書かないはずだ、という
ありそうもない前提に立っているわけですが・・・。



>まどかさん

> 実質スレッドセーフでないのかなと思ったりする。
うーんでも.NET2.0ではこっそりCloneが追加されていたりするところをみると
どうも怪しい気がしないでもないんですよねえ。。
>>実質スレッドセーフでないのかなと思ったりする。

> うーんでも.NET2.0ではこっそりCloneが追加されていたりするところをみると
> どうも怪しい気がしないでもないんですよねえ。。

.NET 2.0からは設定のできるパブリックプロパティが追加されたようなので(それまでは完全に無かったのか、詳しく確認はしていませんが)、そのためにCloneも追加されたという可能性はどうでしょうか?

> ただ、問題がないならないで、その確証というか、理論的な裏づけが
> 欲しいなと思いまして・・・。

本当にそうですね(恥ずかしながら、私は今までこのような危険性に気づいていませんでしたが...)。私は見つけられませんでしたが、どこかに無いものでしょうか?
■No17998に返信(CRTさんの記事)

CRTさん
貴重なデータ 有難うございます。

> いえ、スレッドセーフ「ではない」、という確認がとれているわけではありません。
> というより、むしろ今までの動作を観察する限り、実質的には問題ないようにも思えます。

私も同感です。
> ただ、問題がないならないで、その確証というか、理論的な裏づけが
> 欲しいなと思いまして・・・。


私の解釈を若干補足しますと
Encodingクラスには共有メンバとインスタンスメンバがあります。
これらメンバのなかで「共有メンバはスレッド セーフを保証している」と
解釈するのです。

私の仮定
  共有メンバは新たなインスタンスを作成できない。
  >Dim SJIS0 As Encoding = Encoding.Default
  これは SJIS0 変数に  Encoding.Default を関連付けしただけ。
  インスタンスの作成ではない。
  従ってスレッド セーフを保証している。

  共有メンバでなければ新たなインスタンスを作成できる。
  新たなインスタンスはスレッド セーフを保証していない。
私の仮定終了




>
>
>>Encoding.Default
>>Encoding.GetEncoding(...)
>>は共有メンバ = {public static (Visual Basic では Shared)} と考えると
>>スレッド セーフです。
>
> これはしかし、素直に考えれば上記のプロパティ・メソッドの動作がスレッドセーフである、
> という意味であって、それによって取得されたインスタンスの
> インスタンスメソッド(たとえばGetString)の動作のスレッドセーフまで
> 保障されるとは考えにくいのではないでしょうか?
>
> というより、そもそも.NET 1.1ではこれらの共有メソッド呼び出しでしかEncodingの
> インスタンスを取得できないようですから、エツさんの仮定が正しいとすると
> MSDNライブラリにわざわざ「インスタンスのメンバの場合は、スレッドセーフであるとは限らない」
> と表示する意味がなくなってしまいます。
>
> もっとも、これはMSDNライブラリの書き手は不合理なことは書かないはずだ、という
> ありそうもない前提に立っているわけですが・・・。




従ってこれを書く意味もあります。
>スレッド セーフ
>この型の public static (Visual Basic では Shared) メンバはすべて、スレッド セーフです。>インスタンス メンバの場合は、スレッド セーフであるとは限りません。


#この表現はDateTime 構造体にもありました。
DateTime 構造体から引用(Encodingと全く同じ文言)
スレッド セーフ
この型の public static (Visual Basic では Shared) メンバはすべて、スレッド セーフです。インスタンス メンバの場合は、スレッド セーフであるとは限りません。

#この私の記述は技術的な裏づけはありません。単なるヘルプの記述の解釈だけです。
本当はどうなのか 「スッキリ」 させたいです。

どうか宜しくお願いします。
2006/10/24(Tue) 18:28:01 編集(投稿者)

> 本当はどうなのか 「スッキリ」 させたいです。

なら議論は不要で、サポートに問い合わせるべきです。

ヘルプの記述は(責任回避のための)「お約束」としてすべてのクラスに半ば自動的に書かれているだけに見えるので、その言葉尻を捕まえて議論しても得られるものは少ないと思います。

DOBON.NET | プログラミング道 | プログラミング掲示板