JP4754004B2 - マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム - Google Patents
マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム Download PDFInfo
- Publication number
- JP4754004B2 JP4754004B2 JP2009052560A JP2009052560A JP4754004B2 JP 4754004 B2 JP4754004 B2 JP 4754004B2 JP 2009052560 A JP2009052560 A JP 2009052560A JP 2009052560 A JP2009052560 A JP 2009052560A JP 4754004 B2 JP4754004 B2 JP 4754004B2
- Authority
- JP
- Japan
- Prior art keywords
- code
- class
- method call
- computer system
- lock
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Fee Related
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
- G06F8/45—Exploiting coarse grain parallelism in compilation, i.e. parallelism between groups of instructions
- G06F8/458—Synchronisation, e.g. post-wait, barriers, locks
Landscapes
- Engineering & Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Devices For Executing Special Programs (AREA)
Description
しかし、非特許文献1は、ハッシュ表クラスを並行ハッシュマップ・クラスに自動的に置き換えるアルゴリズムを記載していない。
また、上記で述べた、ハッシュ表クラスの使用を並行ハッシュマップ・クラスの使用に変換するにあたってロック衝突の問題に対応するために、同期マップ・クラスを自動的に置き換えるアルゴリズムを用意する必要がある。
上記第1のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(以下、第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(以下、第2のクラス)が上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードが上記第1のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス(以下、第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が上記第3のクラスよりも短い並行動作可能なクラス(以下、第4のクラス)のメソッド呼び出し(以下、第1のメソッド呼び出し)を含むところのクラスに変換するステップと、
上記第1のプログラム・コードが上記第2のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第2のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(以下、第2のメソッド呼び出し)を含むところのクラスに変換するステップと
を含む。
上記第1のプログラム・コード及び上記変換のコンピュータ・プログラムを格納する記憶部と、
上記コンピュータ・プログラムを上記記憶部からメモリ内に読み出し、下記命令を実行する中央演算処理装置(CPU)であって、該命令が下記命令を含み、該命令が、
ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(第2のクラス)が上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードが上記第1のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス(第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が記第3のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(第1のメソッド呼び出し)を含むところのクラスに変換するステップと、
上記第1のプログラム・コードが上記第2のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第2のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(第2のメソッド呼び出し)を含むところのクラスに変換するステップと
を含む。
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
上記親クラスで定義されているメソッドであって、上記第2のメソッド呼び出しを含むクラスで定義されていない該メソッドを、上記第2のメソッド呼び出しを含むクラスに上記親クラスと同じシグネチャで定義するステップと、
上記同じシグネチャで定義されたメソッドの実装を、上記親クラスで定義されているメソッドを呼び出すコードにするステップと
をさらに含む。
スレッド固有の値をキーとする上記第3のクラスのメソッド呼び出しを含む上記第1のクラスが上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードがスレッド固有の値をキーとする上記第3のクラスのメソッド呼び出しを含むことに応じて、上記第1のクラスを、上記第3のクラスに対応する機能を有し且つ上記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
を含む。
ここで「並行動作可能」とは、ロック衝突が少なく且つ安全にマルチスレッドが実行可能なことである。並行動作可能とは、具体的には、メソッドget()等の取得動作、メソッドput()又はメソッドremove()等の更新操作、及びメソッドputAll又はメソッドclear()等の集計操作によるロック衝突が少なく、且つ、ロックを獲得しないインタフェースIterators/Enumerationsの反復/列挙操作の操作中にConcurrentModificationException等の例外が発生しないことを意味する。並行動作可能なクラスは、例えばハッシュ表クラスに対応する並行ハッシュマップ・クラス(java.util.concurrent.ConcurrentHashMap)及び同期マップ・クラスに対応する並行マップ・クラス(concurrent map class)が該当しうる。なお、並行マップ・クラスには、clone()メソッドなどの固有のメソッドの定義が存在するが、並行ハッシュマップ・クラスには、上記固有のメソッドの定義は含まれない。
コンピュータ・システム(100)は、典型的には、CPU(101)、メモリ(102)、及び記憶部(103)を含む。コンピュータ・システム(100)はまた、入出力部(104)及び通信部(105)を含んでいてもよい。
コンピュータ・システム(100)は、本発明のJavaコードを変換するためのプログラム(106)(以下、変換用プログラム)、該変換用プログラムに従い変換されるプログラム、例えばJavaコード(108)(以下、第1のJavaコード)及び、変換において参照される対応テーブル(107)を記憶部(103)に含む。以下では、変換用プログラムに従い変換されるプログラムがJavaコードである場合を例として説明するが、他のプログラムについても同様に適用することが可能である。
第1のJavaコード(108)は、該コンピュータ・システム(100)の入出力部(104)を介して、又はネットワークを経由して通信部(105)から記憶部(103)に格納されてもよい。CPU(101)は、変換用プログラム(106)を記憶部(103)からメモリ(102)内に読み込む。CPU(101)は、該変換用プログラム(106)の命令を実行し、第1のJavaコード(108)及び対応テーブル(107)を記憶部(103)からメモリ(102)内に読み込み、該読み込んだ第1のJavaコード(108)を、ロック衝突の少ないJavaコード(110)(以下、第2のJavaコード)に変換する。第1のJavaコードから第2のJavaコードへの変換において、変換途中のJavaコード(109)を経てもよい。
対応テーブル(107)は、同期マップ・クラスと並行マップ・クラスとの対応が保存されたテーブルである。対応テーブル(107)には、例えば、同期マップ・クラスのアプリケーション・プログラム・インターフェース(API)と、上記同期マップ・クラスのAPIと同じ機能を提供する並行マップ・クラスのAPIであって、ロックを獲得している区間が上記同期マップ・クラスより短い並行動作可能な上記APIとの組が保存される。コンピュータ・システム(100)は、第1のJavaコード(108)中で同期マップ・クラスのAPIが使われている場合に、同期マップ・クラスのAPIと組をなす並行マップ・クラスのAPIを対応テーブル(107)から求める。これによりコンピュータ・システム(100)は、同期マップ・クラスのAPIを、該求めた並行マップ・クラスのAPIに置き換えることができる。
1.同期マップ・クラスが利用されているクラス
2.同期を取ることが明記されているコレクション・クラスを継承したクラス
同期をとることが明記されているコレクション・クラスとは、例えば、Javaクラス・ライブラリの同期ハッシュ表クラス(java.util.Hashtable)、Javaクラス・ライブラリの同期ベクトルクラス(java.util.Vector)及びJavaクラス・ライブラリの同期スタッククラス(java.util.Stack)である。
本明細書では、同期をとることが明記されているコレクション・クラスを上記同期ハッシュ表クラスとし、上記同期ハッシュ表クラスに対応する並行マップ・クラスを並行ハッシュ表クラス(concurrentHashtable)として説明する。
従って、同期ハッシュ表クラスを継承したクラスを用いた実施態様(図2のステップ202及び図3A〜図3Iの全てのステップ)は、同期を取ることが明記されているコレクション・クラスを継承したクラスでも実施可能である。
3. 同期マップ・クラスのキー(key)をスレッド固有の値で利用しているクラス
コンピュータ・システム(図1、100)は、変換処理の開始に先立って、プログラミング言語Javaによるプログラムである第1のJavaコード(108)を記憶部(図1、103)からメモリ(図1、102)内に読み込む。以下の説明では、上記第1のJavaコード(108)には、1つのクラス(以下、CL)が含まれているとするが、上記第1のJavaコード(108)には、複数のクラスが含まれていてもよい。第1のJavaコード(108)に複数のクラスが含まれる場合、コンピュータ・システム(100)は、以下のステップ200〜207の処理を、全てのクラスについて実行する。
ステップ200は、変換処理の開始である。
ステップ201では、コンピュータ・システム(100)は、入力された第1のJavaコード(108)に含まれるクラス(CL)が同期ハッシュ表クラスを継承しているかどうかの判定を行う。該判定では、コンピュータ・システム(100)が、例えば、CLにおけるクラスの宣言部分に「extends hashtable」が含まれるかどうかをチェックする。「extends hashtable」が含まれる場合、コンピュータ・システム(100)は、CLが同期ハッシュ表クラスを継承していると判定し、該処理はステップ202に進む。一方、「extends hashtable」が含まれない場合、コンピュータ・システム(100)は、CLが同期ハッシュ表クラスを継承していないと判定し、該処理はステップ203に進む。
ステップ202では、コンピュータ・システム(100)は、CLを同期ハッシュ表クラスに対応する並行ハッシュ表クラスを使用するクラスに変換する。すなわち、コンピュータ・システム(100)は、同期ハッシュ表クラスに対応する並行ハッシュ表クラスのインスタンスを新規に作成するコードを、CLに追加する。次に、コンピュータ・システム(100)は、CLのスーパークラス(super class)である同期ハッシュ表クラスに属するメソッドを呼び出すコードを、新規に作成された並行ハッシュ表クラスのインスタンスに属するメソッドを呼び出すコードに置き換える。次に、コンピュータ・システム(100)は、所定のコード変換を行う。該コード変換では、コンピュータ・システム(100)は、上記置き換えられたコードが、所定の条件を満たすことに応じて、CLに含まれるコードを所定のコードに変換する。該変換では、コンピュータ・システム(100)は、例えば、CLから不必要な同期のためのコードを除去する。なお、ステップ202については、図3A〜図3Jの説明において詳しく述べる。次に、該処理はステップ203に進む。
ステップ203では、コンピュータ・システム(100)は、CLの中で同期マップ・クラスが宣言されているかどうかの判定を行う。CLの中で同期マップ・クラスが宣言されている場合、該処理はステップ204に進む。一方、CLの中で同期マップ・クラスが宣言されていない場合、該処理は終了する。
ステップ204では、コンピュータ・システム(100)は、以下の判定処理を行う。すなわち、コンピュータ・システム(100)は、CLの中で宣言されている同期マップ・クラスが提供するメソッドにおいて、マップのキーとしてスレッド固有の値が使われているかどうかの判定を行う。ここで、マップのキーとは、コンピュータ・システム(100)が、マップ・クラスに値(value)を登録する場合に、値(value)との組で指定するキー値である。コンピュータ・システム(100)は、同一のキー値を指定することで、キー値に対応する登録された値(value)をマップ・クラスから取得することができる。また、スレッド固有の値とは、例えば、スレッド・クラスのメソッド(java.lang.Thread.currentThread()又は、java.lang.Thread.getId())である。上記スレッド固有の値が使われている場合、該処理はステップ205に進む。一方、上記スレッド固有の値が使われていない場合、該処理はステップ206に進む。
ステップ205では、コンピュータ・システム(100)は、上記スレッド固有の値をスレッド・ローカルな値に変換する。すなわち、コンピュータ・システム(100)は、スレッド・ローカル・ストレージ(Thread local storage)を確保するコードを、CLに追加する。コンピュータ・システムは、同期マップ・クラスにアクセスするコードを上記スレッド・ローカル・ストレージにアクセスするのコードに置き換える。次に、コンピュータ・システム(100)は、所定のコード変換を行う。該コード変換では、コンピュータ・システムは、上記置き換えられたコードが、所定の条件を満たすことに応じて、CLに含まれるコードを所定のコードに変換する。なお、ステップ205については、図5A〜図5Fの説明において詳しく述べる。次に、該処理はステップ206に進む。
ステップ206では、コンピュータ・システム(100)は、同期マップ・クラスを対応する並行マップ・クラスに変換する。次に、コンピュータ・システム(100)は、所定のコード変換を行う。該コード変換では、コンピュータ・システム(100)は、上記変換されたクラスに含まれるコードが、所定の条件を満たすことに応じて、上記変換されたクラスに含まれるコードを所定のコードに変換する。該変換では、コンピュータ・システム(100)は、例えば、実行時のロック衝突を減らす書き換えが可能なコードをCL内から探し、書き換えを実行する。なお、ステップ206については、図7A〜図7Jの説明において詳しく述べる。コンピュータ・システム(100)は、上記書き換え後に、該処理を終了する。
ステップ207は、変換処理の終了である。
図2のステップ202は、同期ハッシュ表クラスを継承するクラスを同期ハッシュ表クラスに対応する並行ハッシュ表クラスを使用するクラスに変換する処理である。
ステップ300は、図2のステップ202の開始である。
ステップ301では、コンピュータ・システム(100)は、並行ハッシュ表クラスのインスタンスを生成するコードをCLに挿入する。
以下の例では、上記生成された並行ハッシュ表クラスのインスタンスが代入されるプライベート(private)変数をccとする。上記挿入されるコードは、例えば、「private concurrentHashtable cc = new concurrentHashtable();」である。上記挿入の終了に応じて、該処理はステップ302に進む。
ステップ302では、コンピュータ・システム(100)は、CLにおいて、CLが継承しているスーパークラスの呼び出しを修正する。コンピュータ・システム(100)は、CLのスーパークラスである同期ハッシュ表クラスに属し、且つ「super.foo()」という形式で記載されているスーパークラスのメソッド呼び出しを、並行ハッシュ表クラスのインスタンスによる呼び出し「cc.foo()」に置き換える。ここで、foo()は、任意のメソッド名を指す。コンピュータ・システム(100)は、例えば、「super.get(key)」を「cc.get(key)」に置き換える。また、コンピュータ・システム(100)は、クラスのコンストラクタ内のスーパークラス呼び出しである「super()」をCLから削除する。上記置き換え及び削除の終了に応じて、該処理はステップ303に進む。
ステップ303では、コンピュータ・システム(100)は、CLにメソッドを追加する。追加されるメソッドは、同期ハッシュ表クラスに属し、且つCLでは定義されていないメソッドである。
ユーザは、例えば、ファイルに同期ハッシュ表クラスのAPIを保存しておく。コンピュータ・システム(100)は、上記ファイルから、同期ハッシュ表クラスのメソッドにアクセスするためのインタフェース及び同期ハッシュ表クラスのメソッドのシグネチャを取得する。コンピュータ・システム(100)は、CLを精査し、上記インタフェースと同じインタフェースがCLに含まれない場合、上記インタフェースを提供するメソッドの定義をCLに追加する。コンピュータ・システム(100)は、追加するメソッドのシグネチャを、追加するメソッドに対応する上記ファイルから取得した同期ハッシュ表クラスのメソッドと同一のシグネチャにする。また、コンピュータ・システム(100)は、追加するメソッドの実装を「return cc.foo();」とする。ただし、上記追加するメソッドに対応する同期ハッシュ表クラスのメソッドの戻り値がvoidである場合、コンピュータ・システム(100)は、上記追加するメソッドの実装を「cc.foo();」とする。ここで、foo()は、上記追加するメソッドに対応する同期ハッシュ表クラスのメソッドである。
ステップ304では、コンピュータ・システム(100)は、CLのコードを書き換える。コンピュータ・システム(100)は、ステップ302で置き換えられたメソッド呼び出しを含むコード(以下、第1のコード)をロックの獲得及びロックの解放を原子的に実行するためのコード(以下、第2のコード)に書き換える。該書き換えは、下記図3B〜図3Eを参照して別途説明する。
ステップ305では、コンピュータ・システム(100)は、CLに含まれる同期ブロックを修正する。ステップ302においてスーパークラスのメソッド呼び出しに替えて置き換えたメソッド呼び出しが同期ブロックに挟まれている場合、コンピュータ・システム(100)は、該同期ブロックを修正する。該修正は、下記図3F〜図3Jを参照して別途説明する。
・ステップ305は、ステップ301の後で実行されること。
・ステップ302は、ステップ301の後で実行されること。
・ステップ303は、ステップ302の後で実行されること。
・ステップ304は、ステップ302の後で実行されること。但し、ステップ304がステップ303より先に実行される場合、ステップ304がステップ303より後に実行される場合に比べ、コードの書き換えが行われる機会が減る可能性がある。
以下の例では、条件式としてif文を使用しているが、条件式はif文に限らない。条件式は、言語に用意された条件判定を行うための予約語であればよく、例えばSwitch文であってもよい。
ステップ310は、図3Aのステップ304の始まりを示す。
ステップ311では、コンピュータ・システム(100)は、CL内にメソッド呼び出しcc.put(k,v)があるかどうかを判定する。ここで、メソッドput(k,v)は、キー値を指定して該キー値に対応する値を並行ハッシュ表クラスのテーブルに格納するメソッドである。kはキー値を格納する任意の変数を表す。また、vは上記キー値に対応する値を格納する任意の変数を表す。なお、判定されるcc.put(k,v)は、次のステップ312でまだ取り出されていないcc.put(k,v)である。CL内にcc.put(k,v)がある場合、該処理はステップ312に進む。一方、cc.put(k,v)がない場合、ステップ318に進み、終了する。
ステップ313では、コンピュータ・システム(100)は、上記cc.put(k,v)がif文に支配されているかどうかを判定する。cc.put(k,v)がif文に支配されているとは、if文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。cc.put(k,v)がif文に支配されている場合、該処理はステップ314に進む。一方、cc.put(k,v)がif文に支配されていない場合、該処理は311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ314では、コンピュータ・システム(100)は、上記if文の条件節においてcc.get(k)の戻り値がnullと比較されているかどうかを判定する。ここで、メソッドget(k)は、キー値kを指定して該キー値に対応する値を並行ハッシュ表クラスのテーブルから取得するメソッドである。if文の条件節においてcc.get(k)の戻り値がnullと比較されているとは、条件節に例えば「cc.get(k)==NULL」が記載されていることをいう。cc.get(k)の戻り値がnullと比較されている場合、該処理はステップ315に進む。一方、比較されていない場合、該処理はステップ319に進む。
ステップ315では、コンピュータ・システム(100)は、cc.get(k)の戻り値がnullの場合、cc.put(k,v)が実行されるかどうかを判定する。上記戻り値がnullの場合にcc.put(k,v)が実行されるとは、if文が、例えば「if(cc.get(k)==NULL){v=cc.put(k,v);}」の場合である。cc.put(k,v)が実行される場合、該処理はステップ316に進む。一方、cc.put(k,v)が実行されない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ316では、コンピュータ・システム(100)は、cc.get(k)の戻り値がnullと等しくない場合、実行される命令がないかを判定する。上記戻り値がnullと等しくない場合、実行される命令がないとは、if文が、例えば「if(cc.get(k)==NULL){v=cc.put(k,v);}else{//nop}」の場合である。実行される命令がない場合、該処理はステップ317に進む。一方、実行される命令がある場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ317では、コンピュータ・システム(100)は、cc.get(k)がif文を直接支配するかどうかを判定する。cc.get(k)がif文を直接支配するとは、if文が実行される前に必ずcc.get(k)が実行され、且つcc.get(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。cc.get(k)がif文を直接支配する場合、該処理はステップ321に進む。一方、cc.get(k)がif文を直接支配しない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ319では、コンピュータ・システム(100)は、if文の条件節においてcc.containsKey(k)の戻り値を評価しているかどうかを判定する。cc.containsKey(k)の戻り値を評価するとは、条件節に例えば「cc.containsKey(k)==FALSE」が記載されていることをいう。ここで、メソッドcontainsKey(k)は、キー値kを指定して該キー値に対応する値が並行ハッシュ表クラスに含まれるかどうかを返すメソッドである。cc.containsKey(k)の戻り値が評価されている場合、該処理はステップ331に進む。一方、比較されていない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ321では、コンピュータ・システム(100)は、if文がcc.put(k,v)を直接支配するかどうかを判定する。if文がcc.put(k,v)を直接支配するとは、if文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。if文がcc.put(k,v)を直接支配する場合、該処理はステップ322に進む。一方、直接支配しない場合、該処理はステップ325に進む。
ステップ322では、コンピュータ・システム(100)は、上記cc.get(k)の戻り値がnullと等しい場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ325に進む。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ323に進む。
ステップ323では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ324に進む。一方、メソッドが取得されなかった場合、該処理はステップ325に進む。
ステップ324では、コンピュータ・システム(100)は、cc.get(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。上記putIfAbsent()メソッドについては、URL(http://Java.sun.com/Javase/6/docs/api/Java/util/concurrent/ConcurrentMap.html#putIfAbsent(K,%20V))を参照されたい。
ステップ325では、コンピュータ・システム(100)は、cc.get(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでを「if(cc.get(k)== null){synchronized(cc){」と「}}」とで囲む。上記囲むことが終了したら、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ331では、コンピュータ・システム(100)は、cc.containsKey(k)の戻り値がfalseの場合、cc.put(k,v)が実行されるかどうかを判定する。上記戻り値がfalseの場合にcc.put(k,v)が実行されるとは、if文が、例えば「if(cc.containsKey(k)==false){v=cc.put(k,v);}」の場合である。cc.put(k,v)が実行される場合、該処理はステップ332に進む。一方、cc.put(k,v)が実行されない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ332では、コンピュータ・システム(100)は、cc.put(k,v)の戻り値が使用されているかどうかを判定する。cc.put(k,v)の戻り値がCL内で使用されている場合、該処理はステップ333に進む。一方、使用されていない場合、該処理はステップ336に進む。
ステップ333では、コンピュータ・システム(100)は、cc.containsKey(k)の戻り値がtrueの場合、戻り値が使用されるcc.get(k)があるかどうかを判定する。戻り値が使用されるcc.get(k)があるとは、if文が、例えば「if(cc.containsKey(k)==true){v=cc.get(k);}」の場合、vを使用するコードがCLに含まれていることをいう。戻り値が使用されるcc.get(k)が含まれる場合、該処理はステップ334に進む。一方、含まれない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ334では、コンピュータ・システム(100)は、cc.get()及びcc.put()から2つを後支配する位置までに実行される文はあるかどうかを判定する。cc.get()及びcc.put()から2つを後支配する位置とは、cc.get()が実行された後に必ず実行される命令と、cc.put()が実行された後に必ず実行される命令とのうち、最初に共通で実行される命令のコードの位置である。実行される文がない場合、該処理はステップ335に進む。一方、実行される文がある場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ335では、コンピュータ・システム(100)は、cc.containsKey (k)がif文を直接支配するかどうかを判定する。cc.containsKey(k)がif文を直接支配するとは、if文が実行される前に必ずcc.containsKey(k)が実行され、且つcc.containsKey(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。cc.containsKey(k)がif文を直接支配する場合、該処理はステップ341に進む。一方、cc.containsKey(k)がif文を直接支配しない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ336では、コンピュータ・システム(100)は、cc. containsKey(k)の戻り値がtrueの場合、実行される文がないかどうかを判定する。上記戻り値がtrueの場合において、実行される文がないとは、if文が、例えば「if(cc.containsKey(k)==true){//nop}」の場合である。実行される文がない場合、該処理はステップ337に進む。一方、実行される文がある場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ337では、コンピュータ・システム(100)は、cc.containsKey(k)がif文を直接支配するかどうかを判定する。cc.containsKey(k)がif文を直接支配する場合、該処理はステップ346に進む。一方、cc.containsKey(k)がif文を直接支配しない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ341では、コンピュータ・システム(100)は、if文がcc.put(k,v)及びcc.get(k)を直接支配するかどうかを判定する。if文がcc.put(k,v) 及びcc.get(k)を直接支配するとは、if文によって選択制御されるコード部分にcc.put(k,v)及びcc.get(k)が含まれていることをいう。if文がcc.put(k,v)及びcc.get(k)を直接支配する場合、該処理はステップ342に進む。一方、if文がcc.put(k,v)及びcc.get(k)を直接支配しない場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ342では、コンピュータ・システム(100)は、上記cc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ343に進む。
ステップ343では、コンピュータ・システム(100)は、上記cc.containskey(k)の戻り値がtrueの場合に実行されるコード部分において、cc.get(k)の後にも実行文があるかどうかを判定する。cc.get(k)の後にも実行文がある場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。一方、cc.get(k)の後に実行文がない場合、該処理はステップ344に進む。
ステップ344では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ345に進む。一方、メソッドが取得されなかった場合、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ345では、コンピュータ・システム(100)は、cc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ346では、コンピュータ・システム(100)は、if文がcc.put(k,v)を直接支配するかどうかを判定する。if文がcc.put(k,v)を直接支配するとは、if文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。if文がcc.put(k,v)を直接支配する場合、該処理はステップ347に進む。一方、if文がcc.put(k,v)を直接支配しない場合、該処理はステップ350に進む。
ステップ347では、コンピュータ・システム(100)は、上記cc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ350に進む。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ348に進む。
ステップ348では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ349に進む。一方、メソッドが取得されなかった場合、該処理はステップ350に進む。
ステップ349では、コンピュータ・システム(100)は、cc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ350では、コンピュータ・システム(100)は、cc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをif ((v = cc.get(key)) == null) { synchronized(cc) { if ((v =cc.get(key)) == null) { v = cc.put(key, value); } } }で置き換える。上記置き換えることが終了したら、該処理はステップ311に戻り、別のcc.put(k,v)についての処理を開始する。
なお、以下の図3F〜図3Jの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
ステップ305では、コンピュータ・システム(100)は、同期ブロック(以下、SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図3F〜図3J)を行う。
ステップ351は、図3Aのステップ305の始まりを示す。
ステップ352では、コンピュータ・システム(100)は、SB1内に並行ハッシュ表クラスのインスタンスccに属するメソッド呼び出しが1つ以下あるかどうかを判定する。1つ以下あるとは、1つ含まれるか又は含まれないことである。ここで、コンピュータ・システム(100)は、上記ステップ304で書き換えられた結果に含まれているインスタンスccに属するメソッド呼び出しのコードについては、それぞれを1つと数えず、上記書き換えられた結果に含まれているインスタンスccに属するメソッド呼び出しのコード全体を1つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が1つ以下の場合、該処理はステップ353に進む。一方、上記数えられたメソッド呼び出しのコード数が2つ以上の場合、該処理はステップ361に進む。
ステップ353では、コンピュータ・システム(100)は、SB1内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、インスタンス変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ361に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ354に進む。
ステップ354では、コンピュータ・システム(100)は、SB1内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、スタティック変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ361へ進む。一方、上記スタティック変数にアクセスするコードが含まれていない場合、該処理はステップ355に進む。
ステップ355では、コンピュータ・システム(100)は、SB1を除去する。上記除去は、コンピュータ・システム(100)が、コードからSB1についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ356へ進み、ステップ305は終了する。
上記ステップ351〜355の処理によって、ロック衝突の機会が減少する。
ステップ361では、コンピュータ・システム(100)は、SB1内にv = cc.get()が1つだけ存在するかどうかを判定する。コンピュータ・システム(100)は、SB1で囲まれているインスタンスccからのgetメソッド呼び出し(v =cc.get())のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が1つの場合、該処理はステップ362に進む。一方、上記getメソッドの数が0又は2以上の場合、該処理はステップ371に進む。
ステップ362では、コンピュータ・システム(100)は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム(100)は、上記戻り値vについてのnullチェックをするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ363に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ371に進む。
ステップ363では、コンピュータ・システム(100)は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計2回以上あるかどうかを判定する。コンピュータ・システム(100)は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計2回以上ある場合、該処理はステップ364に進む。一方、上記アクセスするコードが0または1回ある場合、該処理はステップ371に進む。
ステップ364では、コンピュータ・システム(100)は、SB1の外側にif((v=cc.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ365に進む。ステップ365は、ステップ305の終了を示す。
上記ステップ361〜365の処理によって、ロック衝突時間が短縮される。
ステップ371では、コンピュータ・システム(100)は、SB1内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理は、ステップ376に進み終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ372に進む。
ステップ372では、コンピュータ・システム(100)は、SB1内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理はステップ376に進み、終了する。一方、上記書き込みコードが含まれていない場合、該処理は、ステップ373に進む。
ステップ373では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているインスタンスccに属する参照に関するメソッド呼び出しのコードの数(M)を数える。インスタンスccに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ374では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値(N)を求める。
ステップ375では、コンピュータ・システム(100)は、M+N>=2が成り立つかどうかを判定する。コンピュータ・システム(100)は、M+Nを計算する。M+Nが2以上の場合、該処理はステップ381に進む。一方、M+Nが1以下の場合、該処理はステップ376に進み、終了する。
ステップ381では、コンピュータ・システム(100)は、SB1にアクセスがあるccについての更新に関する呼び出しが、CL内にも存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査によって、SB1に囲まれた範囲に含まれているインスタンスccに属する更新に関するメソッド呼び出しに対応する、インスタンスccに属する更新に関するメソッド呼び出しのコードがCL内に発見された場合、該処理はステップ382に進む。一方、発見されなかった場合、該処理はステップ385に進む。ここで、ccに属する更新に関するメソッド呼び出しとは、例えば、cc.put()である。
ステップ382では、コンピュータ・システム(100)は、発見された更新に関する呼び出しが第2の同期ブロック(以下、SB2)で囲まれているかどうかを判定する。コンピュータ・システム(100)は、上記発見されたコードが、SB2で囲まれた範囲に含まれているかどうかを調べる。含まれている場合、該処理はステップ383に進む。一方、含まれていない場合、該処理はステップ385に進む。
ステップ383では、コンピュータ・システム(100)は、SB2内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB2に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ385に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ384に進む。
ステップ384では、コンピュータ・システム(100)は、SB1のロックをリード・ロックに置き換える。また、コンピュータ・システム(100)は、SB2のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ385に進む。
ステップ385では、コンピュータ・システム(100)は、ステップ374で求めた合計値(N)を判定する。N>0の場合、該処理はステップ387に進む。一方、N>0以外の場合、該処理はステップ386に進み、終了する。
ステップ387では、コンピュータ・システム(100)は、SB1内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがCL内に存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査により、SB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はSB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数への書き込み、CL内に発見された場合、該処理はステップ388に進む。一方、発見されなかった場合、該処理はステップ392に進み、終了する。
ステップ388では、コンピュータ・システム(100)は、発見された更新が第3の同期ブロック(以下、SB3)で囲まれているかどうかを判定する。上記発見されたコードがSB3に含まれている場合、該処理はステップ389に進む。一方、含まれていない場合、該処理はステップ392に進み、終了する。
ステップ389では、コンピュータ・システム(100)は、SB3内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB3に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ392に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ390に進む。
ステップ390では、コンピュータ・システム(100)は、SB1のロックがリード・ロックに置き換わっていないならば、SB1の該ロックをリード・ロックに置き換える。
ステップ391では、コンピュータ・システム(100)は、SB3のロックをライト・ロックに置き換える。
ステップ392及びステップ393はいずれも、ステップ305の終了を示す。
図4Aは、第1のコードと第2のコードとの対応を示す。コード(401)及びコード(402)は、第1のコードの例である。コード(403)及びコード(404)は、第2のコードの例である。
コンピュータ・システム(100)は、コード(401)及びコード(402)それぞれについて、図3Aのステップ304(詳細には、図3B〜図3Eの各ステップ)の処理を行う。該処理により、コード(401)及びコード(402)は、コード(403)又はコード(404)に書き換えられる。ここで、ccがメソッド(get()/put())の組を原子的に実行するputIfAbsent()メソッドを持っている並行ハッシュ表クラスのインスタンスである場合、コード(401)及びコード(402)は、コード(403)に変換される。putIfAbsent()メソッドを持っていない並行ハッシュ表クラスのインスタンスである場合、コード(401)及びコード(402)は、コード(404)に変換される。
図4Cは、本発明の実施態様における、図1に示すメモリ(102)内にある第2のJavaコード(110)であるCL(クラスX)を示す。
以下に、図4Bに示す変換前の第1のJavaコードであるCL(クラスX)を、図3Aに示す変換処理を適用して、図4Cに示す変換後の第2のJavaコードであるCL(クラスX)に変換する例を示す。
コンピュータ・システム(100)は、図3Aのステップ301(インスタンスを生成するコードの挿入)に従い、ハッシュ表クラスに対応する並行ハッシュ表クラスのインスタンスを生成するコードをクラスXに挿入する。挿入されたコードは、「private concurrentHashtable cc = new concurrentHashtable();」である(図4Cの//X’00を見よ)。
コンピュータ・システム(100)は、図3Aのステップ302(スーパークラスの呼び出しの修正)に従い、スーパークラスの呼び出しを修正する。この修正により、コンストラクタ内のスーパークラスの呼び出し(図4Bの//X02を見よ)は、削除されるか、又はコメント化されたスーパークラスの呼び出し(図4Cの//X’02を見よ)に修正される。また、スーパークラスの呼び出し(図4Bの//X05,//X09,//X22を見よ)は、並行ハッシュ表クラスのインスタンスccの呼び出し(図4Cの//X’05,//X’07,//X’19,//X’22を見よ)に修正される。
コンピュータ・システム(100)は、ステップ303(同期ハッシュ表クラスに属するメソッドの追加)に従い、メソッドを追加する。なお、クラスXには、ステップ303によって追加されるメソッドはない。
コンピュータ・システム(100)は、ステップ304(コードの書き換え)に従い、コードを書き換える。なお、本クラスXには、ステップ304によって書き換えられるコードはない。
コンピュータ・システム(100)は、ステップ305(同期ブロックの修正)に従い、コードを書き換える。//X04〜//X10では、ccに関するアクセスは//X05のcc.get()だけである。また、//X06のif (ret == null) { … }のパスにおいて、parentが2回以上参照されている。よって、//X04の同期修飾子(synchronized)が除去される。また、//X06のif (ret == null) { … }のパスが同期ブロックで囲まれ、「ret=cc.get();if(ret == null) 」が同期ブロックの外側に複製される。
よって、変換後の第2のJavaコードは、図4Cに示すコードになる。
図2のステップ205は、同期マップ・クラスが提供するメソッドにおいて、マップのキーとしてスレッド固有の値が使われている場合の変換処理である。
ステップ500は、図2のステップ205の開始である。
ステップ501では、コンピュータ・システム(100)は、同期マップ・クラスのインスタンス生成コードが使用されている場合、スレッド・ローカル・クラス(java.lang.ThreadLocal)のインスタンスを生成するコードに置き換える。新たに挿入されるコードは、例えば、「ThreadLocal tlh = new ThreadLocal();」である。
ここで、「スレッド・ローカル・クラス」とは、スレッド・ローカル変数、すなわち1つの論理変数でありながら、別々のスレッドで独立した値をもつことを可能にする変数を提供するクラスである。
なお、本明細書では、生成されたスレッド・ローカル・クラスのインスタンスが代入されるprivate変数をtlh、同期マップ・クラスのインスタンス変数をsc、スレッド固有の値をthrとする。
ステップ502では、同期マップ・クラスのインスタンスからのメソッド呼び出しを、上記スレッド・ローカルなインスタンスからのメソッド呼び出しに置き換える。具体的には、thr をthread 固有の値としたときに、同期マップ・クラスのインスタンスscによるメソッド呼び出しsc.get(thr)をスレッド・ローカル・クラスのインスタンスtlhによるメソッド呼び出しtlh.get()に、インスタンスscによるメソッド呼び出しsc.put(thr, value)をスレッド・ローカル・クラスのインスタンスtlhによるメソッド呼び出しtlh.put(value)に、インスタンスscによるメソッド呼び出しsc.remove(thr)をスレッド・ローカル・クラスのインスタンスtlhによるメソッド呼び出しtlh.remove()に置き換える。さらに、コンピュータ・システム(100)は、不要コード除去(dead code elimination)を適用しうる。該適用によって、不要な代入文が削除される。
ステップ503において、ステップ501及び502で置き換えたメソッドが同期ブロックで囲まれている場合、下記の処理を行う。
(a)同期ブロックの中に他のインスタンス変数とスタティック変数とが存在しない場合、同期ブロックを除去する。
(b)同期ブロックの中で、インスタンスtlhによるメソッド呼び出しtlh.get()が1つだけ存在する(ア)。上記tlh.get()の戻り値がnullの場合に実行されるパスに、インスタンス変数とスタティック変数の読み書きが2回以上ある(イ)。上記(ア、イ)を満たす場合、もとの同期ブロックを除去する。また、tlh.get()の戻り値がnullの場合に実行されるパスを同期ブロックで囲む。該同期ブロックの内側に「v = tlh.get(); if (v== null)」を複製する。
(c)同期ブロックの中で、インスタンスtlhによるメソッド呼び出しtlh に属する参照メソッド呼び出し(ステップ502の書き換え結果は1つと数える)とプライベートなインスタンス変数とスタティック変数との読み出しの数があわせて2つ以上である場合、同期ブロックをリード・ロック(read lock)に置き換える。
さらに、クラス全体で上記のペアに関する変更(プライベートなインスタンス変数とスタティック変数の書き込み)が存在する同期ブロックの内側でライト・ロック(write lock)を挿入する。
なお、図5Aのステップ502及びステップ503は、どちらのステップが先に実行されてもよい。
ステップ503では、コンピュータ・システム(100)は、同期ブロック(SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図5B〜図5F)を行う。
なお、以下の図5B〜図5Fの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
ステップ551は、図5Aのステップ503の始まりを示す。
ステップ552では、コンピュータ・システム(100)は、SB1内にインスタンスtlhに属するメソッド呼び出しが1つ以下あるかどうかを判定する。1つ以下あるとは、1つ含まれるか又は含まれないことである。ここで、コンピュータ・システム(100)は、上記ステップ502で書き換えられた結果に含まれているインスタンスtlhに属するメソッド呼び出しのコードについては、それぞれを1つと数えず、上記書き換えられた結果に含まれているインスタンスtlhに属するメソッド呼び出しのコード全体を1つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が1つ以下の場合、該処理はステップ553に進む。一方、上記数えられたメソッド呼び出しのコード数が2つ以上の場合、該処理はステップ561に進む。
ステップ553では、コンピュータ・システム(100)は、SB1内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、インスタンス変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ561に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ554に進む。
ステップ554では、コンピュータ・システム(100)は、SB1内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、スタティック変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理は、ステップ561へ進む。一方、上記スタティック変数にアクセスするコードが含まれていない場合、該処理はステップ555に進む。
ステップ555では、コンピュータ・システム(100)は、SB1を除去する。上記除去は、コンピュータ・システム(100)が、コードからSB1についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ556へ進み、ステップ503は終了する。
上記ステップ551〜555の処理によって、ロック衝突の機会が減少する。
ステップ561では、コンピュータ・システム(100)は、SB1内にv = tlh.get()が1つだけ存在するかどうかを判定する。コンピュータ・システム(100)は、SB1で囲まれているインスタンスtlhからのgetメソッド呼び出し(v= tlh.get())のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が1つの場合、該処理はステップ562に進む。一方、上記getメソッドの数が0又は2以上の場合、該処理はステップ571に進む。
ステップ562では、コンピュータ・システム(100)は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム(100)は、上記戻り値vについてのnullチェックをするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ563に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ571に進む。
ステップ563では、コンピュータ・システム(100)は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計2回以上あるかどうかを判定する。コンピュータ・システム(100)は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計2回以上ある場合、該処理はステップ564に進む。一方、上記アクセスするコードが0又は1回ある場合、該処理はステップ571に進む。
ステップ564では、コンピュータ・システム(100)は、SB1の外側にif((v= tlh.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ565に進む。ステップ565は、ステップ503の終了を示す。
上記ステップ561〜565の処理によって、ロック衝突時間が短縮される。
ステップ571では、コンピュータ・システム(100)は、SB1内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ576に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理は、ステップ572に進む。
ステップ572では、コンピュータ・システム(100)は、SB1内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理はステップ576に進み、終了する。一方、上記書き込みコードが含まれていない場合、該処理はステップ573に進む。
ステップ573では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているインスタンスscに属する参照に関するメソッド呼び出しのコードの数(M)を数える。インスタンスscに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ574では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値(N)を求める。
ステップ575では、コンピュータ・システム(100)は、M+N>=2が成り立つかどうかを判定する。コンピュータ・システム(100)は、M+Nを計算する。M+Nが2以上の場合、該処理はステップ581に進む。一方、M+Nが1以下の場合、該処理はステップ576に進み、終了する。
ステップ581では、コンピュータ・システム(100)は、SB1にアクセスがあるtlhについての更新に関する呼び出しが、CL内にも存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査によって、SB1に囲まれた範囲に含まれているインスタンスtlhに属する更新に関するメソッド呼び出しに対応する、インスタンスtlhに属する更新に関するメソッド呼び出しのコードがCL内に発見された場合、該処理はステップ582に進む。一方、発見されなかった場合、該処理はステップ585に進む。ここで、tlhに属する更新に関するメソッド呼び出しとは、例えば、tlh.put()である。
ステップ582では、コンピュータ・システム(100)は、発見された更新に関する呼び出しが第2の同期ブロック(以下、SB2)で囲まれているかどうかを判定する。コンピュータ・システム(100)は、上記発見されたコードが、SB2で囲まれた範囲に含まれているかを調べる。含まれている場合、該処理はステップ583に進む。一方、含まれていない場合、該処理はステップ585に進む。
ステップ583では、コンピュータ・システム(100)は、SB2内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB2に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ585に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ584に進む。
ステップ584では、コンピュータ・システム(100)は、SB1のロックをリード・ロックに置き換える。また、コンピュータ・システム(100)は、SB2のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ585へ進む。
ステップ585では、コンピュータ・システム(100)は、ステップ574で求めた合計値(N)を判定する。N>0の場合、ステップ587に進む。一方、N>0以外の場合、該処理はステップ586に進み、終了する。
ステップ587では、コンピュータ・システム(100)は、SB1内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがCL内に存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査により、SB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はSB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数を更新するコードが、CL内に発見された場合、該処理はステップ588に進む。一方、発見されなかった場合、該処理はステップ592に進み、終了する。
ステップ588では、コンピュータ・システム(100)は、発見された更新が第3の同期ブロック(以下、SB3)で囲まれているかどうかを判定する。コンピュータ・システム(100)は、上記発見されたコードが、SB3で囲まれた範囲に含まれているかを調べる。上記発見されたコードがSB3に含まれている場合、該処理はステップ589に進む。一方、含まれていない場合、該処理はステップ592に進み、終了する。
ステップ589では、コンピュータ・システム(100)は、SB3内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB3に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ592に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ590に進む。
ステップ590では、コンピュータ・システム(100)は、SB1のロックがリード・ロックに置き換わっていないならば、SB1の該ロックをリード・ロックに置き換える。
ステップ591では、コンピュータ・システム(100)は、SB3のロックをライト・ロックに置き換える。
ステップ592及び593のいずれも、ステップ503の終了を示す。
図6Bは、図1に示すメモリ(102)内にある第2のJavaコード(110)であるCL(クラスY)を示す。
以下に、図6Aに示す変換前の第1のJavaコードであるCL(クラスY)を、図5Aに示す変換処理を適用して、図6Bに示変換後の第2のJavaコードであるCL(クラスY)に変換する例を示す。
クラスYは、ハッシュ表クラスを継承しておらず、図2のステップ201の条件を満たさない。また、クラスYは、同期マップ・クラスが宣言されており(図6AのY00)、且つスレッド固有の値threadがキーとして使用されているので(例えば、図6AのY06)、図2のステップ203及び204の条件を満たす。よって、クラスYは、図5Aの各ステップで変換処理される。
次に、図5Aのステップ502によって、固有のスレッドthreadを引数に有する図6Aの//Y05、//Y10、//Y13 が書き換えられる。その結果、図6Bの//Y’05、//Y’10、//Y’13のように書き換えられる。その後、さらに、//Y04、//Y09が削除される。
図6Aでは、同期ブロックに囲まれた部分はないので、ステップ503によって書き換えられるコードはない。よって、変換後の第2のJavaコードは、図6Bに示すコードになる。
ステップ700は、図2のステップ206の開始である。
ステップ701では、コンピュータ・システム(100)は、同期マップ・クラスのインスタンスscを生成しているコードを、同期マップ・クラスに対応する並行マップ・クラスのインスタンスを生成するコードに置き換える。本明細書では、並行マップ・クラスをconcurrentMapというクラスとする。また、本明細書では、生成された上記並行マップ・クラスのインスタンスが代入されるプライベート変数もscとする。さらに、コンピュータ・システム(100)は、上記scに関する型宣言を必要に応じて置き換える。
ステップ702では、コンピュータ・システム(100)は、CLのコードを書き換える。コンピュータ・システム(100)は、ステップ701で置き換えられたメソッド呼び出しを含むコード(以下、第1のコード)をロックの獲得及びロックの解放を原子的に実行するためのコード(以下、第2のコード)に書き換える。該書き換えは、下記図7B〜図7Eを参照して別途説明する。
ステップ703では、コンピュータ・システム(100)は、ステップ701及び702で置き換えたメソッドが同期ブロックで囲まれている場合、同期ブロックを修正する。該修正は、下記図7F〜図7Jを参照して別途説明する。
なお、図7Aのステップ702及びステップ703は、どちらのステップが先に実行されてもよい。
以下の例では、条件式としてif文を使用しているが、条件式はif文に限らない。条件式は、言語に用意された判定を行うための予約語であればよく、例えばSwitch文であってもよい。
ステップ710は、図7Aのステップ702の始まりを示す。
ステップ711では、コンピュータ・システム(100)は、CL内にメソッド呼び出しsc.put(k,v)があるかどうかを判定する。ここで、メソッドput(k,v)は、キー値を指定して該キー値に対応する値を並行マップ・クラスのテーブルに格納するメソッドである。kはキー値を格納する任意の変数を表す。また、vは上記キー値に対応する値を格納する任意の変数を表す。なお、判定されるsc.put(k,v)は、次のステップ712でまだ取り出されていないsc.put(k,v)である。CL内にsc.put(k,v)がある場合、該処理はステップ712に進む。一方、sc.put(k,v)がない場合、ステップ718に進み、終了する。
ステップ713では、コンピュータ・システム(100)は、上記sc.put(k,v)がif文に支配されているかどうかを判定する。sc.put(k,v)がif文に支配されているとは、if文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。sc.put(k,v)がif文に支配されている場合、該処理はステップ714に進む。一方、支配されていない場合、該処理は711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ714では、コンピュータ・システム(100)は、上記if文の条件節においてsc.get(k)の戻り値がnullと比較されているかどうかを判定する。ここで、メソッドget(k)は、キー値kを指定して該キー値に対応する値を並行マップ・クラスのテーブルから取得するメソッドである。if文の条件節においてsc.get(k)の戻り値がnullと比較されているとは、条件節に例えば「sc.get(k)==NULL」が記載されていることをいう。sc.get(k)の戻り値がnullと比較されている場合、該処理はステップ715に進む。一方、比較されていない場合、該処理はステップ719に進む。
ステップ715では、コンピュータ・システム(100)は、sc.get(k)の戻り値がnullの場合、sc.put(k,v)が実行されるかどうかを判定する。上記戻り値がnullの場合にsc.put(k,v)が実行されるとは、if文が、例えば「if(sc.get(k)==NULL){v=sc.put(k,v);}」の場合である。sc.put(k,v)が実行される場合、該処理はステップ716に進む。一方、sc.put(k,v)が実行されない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ716では、コンピュータ・システム(100)は、sc.get(k)の戻り値がnullと等しくない場合、実行される命令がないかどうかを判定する。上記戻り値がnullと等しくない場合、実行される命令がないとは、if文が、例えば「if(sc.get(k)==NULL){v=sc.put(k,v);}else{//nop}」の場合である。実行される命令がない場合、該処理はステップ717に進む。一方、実行される命令がある場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ717では、コンピュータ・システム(100)は、sc.get(k)がif文を直接支配するかどうかを判定する。sc.get(k)がif文を直接支配するとは、if文が実行される前に必ずsc.get(k)が実行され、且つsc.get(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。
sc.get(k)がif文を直接支配する場合、該処理はステップ721に進む。一方、sc.get(k)がif文を直接支配しない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ719では、コンピュータ・システム(100)は、if文の条件節においてsc.containsKey(k)の戻り値を評価しているかどうかを判定する。sc.containsKey(k)の戻り値を評価するとは、条件節に例えば「sc.containsKey(k)==FALSE」が記載されていることをいう。ここで、メソッドcontainsKey(k)は、キー値kを指定して該キー値に対応する値が並行マップ・クラスに含まれるかどうかを返すメソッドである。sc.containsKey(k)の戻り値が評価されている場合、該処理はステップ731に進む。一方、評価されていない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ721では、コンピュータ・システム(100)は、if文がsc.put(k,v)を直接支配するかどうかを判定する。if文がsc.put(k,v)を直接支配するとは、if文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。if文がsc.put(k,v)を直接支配する場合、該処理はステップ722に進む。一方、直接支配しない場合、該処理はステップ725に進む。
ステップ722では、コンピュータ・システム(100)は、上記sc.get(k)の戻り値がnullと等しい場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ725に進む。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ723に進む。
ステップ723では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ724に進む。一方、メソッドが取得されなかった場合、該処理はステップ725に進む。
ステップ724では、コンピュータ・システム(100)は、sc.get(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ725では、コンピュータ・システム(100)は、sc.get(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでを「if(sc.get(k)== null){synchronized(sc){」と「}}」とで囲む。上記囲むことが終了したら、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ731では、コンピュータ・システム(100)は、sc.containsKey(k)の戻り値がfalseの場合、sc.put(k,v)が実行されるかどうかを判定する。上記「戻り値がfalseの場合にsc.put(k,v)が実行される」とは、if文が、例えば「if(sc.containsKey(k)==false){v=sc.put(k,v);}」の場合である。sc.put(k,v)が実行される場合、該処理はステップ732に進む。一方、sc.put(k,v)が実行されない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ732では、コンピュータ・システム(100)は、sc.put(k,v)の戻り値が使用されているかどうかを判定する。sc.put(k,v)の戻り値がCL内で使用されている場合、該処理はステップ733に進む。一方、使用されていない場合、該処理はステップ736に進む。
ステップ733では、コンピュータ・システム(100)は、sc.containsKey(k)の戻り値がtrueの場合、戻り値が使用されるsc.get(k)があるかどうかを判定する。「戻り値が使用されるsc.get(k)がある」とは、if文が、例えば「if(sc.containsKey(k)==true){v=sc.get(k);}」の場合、vを使用するコードがCLに含まれていることをいう。戻り値が使用されるsc.get(k)が含まれる場合、該処理はステップ734に進む。一方、含まれない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ734では、コンピュータ・システム(100)は、sc.get()及びsc.put()から2つを後支配する位置までに実行される文があるかどうかを判定する。sc.get()及びsc.put()から2つを後支配する位置とは、sc.get()が実行された後に必ず実行される命令と、sc.put()が実行された後に必ず実行される命令とのうち、最初に共通で実行される命令のコードの位置である。実行される文がない場合、該処理はステップ735に進む。一方、実行される文がある場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ735では、コンピュータ・システム(100)は、sc.containsKey(k)がif文を直接支配するかどうかを判定する。sc.containsKey(k)がif文を直接支配するとは、if文が実行される前に必ずsc.containsKey(k)が実行され、且つsc.containsKey(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。
sc.containsKey(k)がif文を直接支配する場合、該処理はステップ741に進む。一方、sc.containsKey(k)がif文を直接支配しない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ736では、コンピュータ・システム(100)は、sc. containsKey(k)の戻り値がtrueの場合、実行される文がないかどうかを判定する。上記戻り値がtrueの場合、実行される文がないとは、if文が、例えば「if(sc.containsKey(k)==true){//nop}」の場合である。実行される文がない場合、該処理はステップ737に進む。一方、実行される文がある場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ737では、コンピュータ・システム(100)は、sc.containsKey(k)がif文を直接支配するかどうかを判定する。sc.containsKey(k)がif文を直接支配する場合、該処理はステップ746に進む。一方、sc.containsKey(k)がif文を直接支配しない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ741では、コンピュータ・システム(100)は、if文がsc.put(k,v)及びsc.get(k)を直接支配するかどうかを判定する。if文がsc.put(k,v) 及びsc.get(k)を直接支配するとは、if文によって選択制御されるコード部分にsc.put(k,v)及びsc.get(k)が含まれていることをいう。if文がsc.put(k,v)及びsc.get(k)を直接支配する場合、該処理はステップ742に進む。一方、if文がsc.put(k,v)及びsc.get(k)を直接支配しない場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ742では、コンピュータ・システム(100)は、上記sc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ743に進む。
ステップ743では、コンピュータ・システム(100)は、上記sc.containskey(k)の戻り値がtrueの場合に実行されるコード部分において、sc.get(k)の後にも実行文があるかどうかを判定する。sc.get(k)の後にも実行文がある場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。一方、sc.get(k)の後に実行文がない場合、該処理はステップ744に進む。
ステップ744では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ745に進む。一方、メソッドが取得されなかった場合、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ745では、コンピュータ・システム(100)は、sc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ746では、コンピュータ・システム(100)は、if文がsc.put(k,v)を直接支配するかどうかを判定する。if文がsc.put(k,v)を直接支配するとは、if文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。if文がsc.put(k,v)を直接支配する場合、該処理はステップ747に進む。一方、if文がsc.put(k,v)を直接支配しない場合、該処理はステップ750に進む。
ステップ747では、コンピュータ・システム(100)は、上記sc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ750に進む。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ748に進む。
ステップ748では、コンピュータ・システム(100)は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム(100)は、対応テーブル(107)を、例えばクラス名(java.util.Hashtable)で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ749に進む。一方、メソッドが取得されなかった場合、該処理はステップ750に進む。
ステップ749では、コンピュータ・システム(100)は、sc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ750では、コンピュータ・システム(100)は、sc.containsKey(k)からif文の条件が成り立った場合及び成り立たない場合のコードまでをif ((v = sc.get(key)) == null) { synchronized(sc) { if ((v =sc.get(key)) == null) { v = sc.put(key, value); } } }で置き換える。上記置き換えることが終了したら、該処理はステップ711に戻り、別のsc.put(k,v)についての処理を開始する。
なお、以下の図7F〜図7Jの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
ステップ703では、コンピュータ・システム(100)は、同期ブロック(以下、SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図7F〜図7J)を行う。
ステップ751は、図7Aのステップ703の始まりを示す。
ステップ752では、コンピュータ・システム(100)は、SB1内に並行マップ・クラスのインスタンスscに属するメソッド呼び出しが1つ以下あるかどうかを判定する。1つ以下あるとは、1つ含まれるか又は含まれないことである。ここで、コンピュータ・システム(100)は、上記ステップ702で書き換えられた結果に含まれているインスタンスscに属するメソッド呼び出しのコードについては、それぞれを1つと数えず、上記書き換えられた結果に含まれているインスタンスscに属するメソッド呼び出しのコード全体を1つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が1つ以下の場合、該処理はステップ753に進む。一方、上記数えられたメソッド呼び出しのコード数が2つ以上の場合、該処理はステップ761に進む。
ステップ753では、コンピュータ・システム(100)は、SB1内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、インスタンス変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ761に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ754に進む。
ステップ754では、コンピュータ・システム(100)は、SB1内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、スタティック変数にアクセスするコードが、SB1に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ761へ進む。一方、上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ755に進む。
ステップ755では、コンピュータ・システム(100)は、SB1を除去する。上記除去は、コンピュータ・システム(100)が、コードからSB1についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ756へ進み、ステップ703は終了する。
上記ステップ751〜755の処理によって、ロック衝突の機会が減少する。
ステップ761では、コンピュータ・システム(100)は、SB1内にv = sc.get()が1つだけ存在するかどうかを判定する。コンピュータ・システム(100)は、SB1で囲まれているインスタンスscからのgetメソッド呼び出し(v =sc.get())のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が1つの場合、該処理はステップ762に進む。一方、上記getメソッドの数が0又は2以上の場合、該処理はステップ771に進む。
ステップ762では、コンピュータ・システム(100)は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム(100)は、上記戻り値vについてのnullチェックをするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ763に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ771に進む。
ステップ763では、コンピュータ・システム(100)は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計2回以上あるかどうかを判定する。コンピュータ・システム(100)は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計2回以上ある場合、該処理はステップ764に進む。一方、上記アクセスするコードが0または1回ある場合、該処理はステップ771に進む。
ステップ764では、コンピュータ・システム(100)は、SB1の外側にif((v=sc.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ765に進む。ステップ765は、ステップ705の終了を示す。
上記ステップ761〜765の処理によって、ロック衝突時間が短縮される。
ステップ771では、コンピュータ・システム(100)は、SB1内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ776に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ772に進む。
ステップ772では、コンピュータ・システム(100)は、SB1内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがSB1に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理は、ステップ776に進み終了する。一方、上記書き込みコードが含まれていない場合、該処理はステップ773に進む。
ステップ773では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているインスタンスscに属する参照に関するメソッド呼び出しのコードの数(M)を数える。インスタンスscに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ774では、コンピュータ・システム(100)は、SB1に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値(N)を求める。
ステップ775では、コンピュータ・システム(100)は、M+N>=2が成り立つかどうかを判定する。コンピュータ・システム(100)は、M+Nを計算する。M+Nが2以上の場合、該処理はステップ781に進む。一方、M+Nが1以下の場合、該処理はステップ776に進み、終了する。
ステップ781では、コンピュータ・システム(100)は、SB1でアクセスがあるscについての更新に関する呼び出しが、CL内にも存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査によって、SB1に囲まれた範囲に含まれているインスタンスscに属する更新に関するメソッド呼び出しに対応する、インスタンスscに属する更新に関するメソッド呼び出しのコードがCL内に発見された場合、該処理はステップ782に進む。一方、発見されなかった場合、該処理はステップ785に進む。ここで、scに属する更新に関するメソッド呼び出しとは、例えば、sc.put()である。
ステップ782では、コンピュータ・システム(100)は、発見された更新に関する呼び出しが第2の同期ブロック(以下、SB2)で囲まれているかどうかを判定する。コンピュータ・システム(100)は、上記発見されたコードが、SB2で囲まれた範囲に含まれているかを調べる。含まれている場合、該処理はステップ783に進む。一方、含まれていない場合、該処理はステップ785に進む。
ステップ783では、コンピュータ・システム(100)は、SB2内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB2に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ785に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ784に進む。
ステップ784では、コンピュータ・システム(100)は、SB1のロックをリード・ロックに置き換える。また、コンピュータ・システム(100)は、SB2のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ785に進む。
ステップ785では、コンピュータ・システム(100)は、ステップ774で求めた合計値(N)を判定する。N>0の場合、ステップ787に進む。一方、N>0以外の場合、該処理はステップ786に進み、終了する。
ステップ787では、コンピュータ・システム(100)は、SB1内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがCL内に存在するかどうかを判定する。コンピュータ・システム(100)は、上記SB1を含むクラスのコード全体を精査する。該精査により、SB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はSB1に囲まれた範囲で読み込みが行われているプライベートなスタティック変数を更新するコードが、CL内に発見された場合、該処理はステップ788に進む。一方、発見されなかった場合、該処理はステップ792に進み、終了する。
ステップ788では、コンピュータ・システム(100)は、発見された更新が第3の同期ブロック(以下、SB3)で囲まれているかどうかを判定する。コンピュータ・システム(100)は、上記発見されたコードが、SB3で囲まれた範囲に含まれているかを調べる。上記発見されたコードがSB3に含まれている場合、該処理はステップ789に進む。一方、含まれていない場合、該処理はステップ792に進み、終了する。
ステップ789では、コンピュータ・システム(100)は、SB3内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム(100)は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがSB3に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ792に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ790に進む。
ステップ790では、コンピュータ・システム(100)は、SB1のロックがリード・ロックに置き換わっていないならば、SB1の該ロックをリード・ロックに置き換える。
ステップ791では、コンピュータ・システム(100)は、SB3のロックをライト・ロックに置き換える。
ステップ792及び793のいずれも、ステップ703の終了を示す。
図8Aは、第1のコードと第2のコードとの対応を示す。コード(801)及びコード(802)は、第1のコードの例である。コード(803)及びコード(804)は、第2のコードの例である。
コンピュータ・システム(100)は、コード(801)及びコード(802)それぞれについて、図7Aのステップ702(詳細には、図7B〜図7Eの各ステップ)の処理を行う。該処理により、コード(801)及びコード(802)は、コード(803)又はコード(804)に書き換えられる。ここで、scがメソッド(get()/put())の組を原子的に実行するputIfAbsent()メソッドを持っている並行マップ・クラスのインスタンスである場合、コード(801)及びコード(802)は、コード(803)に変換される。putIfAbsent()メソッドを持っていない並行マップ・クラスのインスタンスである場合、コード(801)及びコード(802)は、コード(804)に変換される。
図8C、本発明の実施態様における、図1に示すメモリ(102)内にある変換後の第2のJavaコードであるCL(クラスZ)を示す。
以下に、図8Bに示す変換前の第1のJavaコードであるCL(クラスZ)を、図7Aに示す変換処理を適用して、図8Cに示す変換後の第2のJavaコードであるCL(クラスZ)に変換する例を示す。
ステップ702では、このCLでは書き換えられるコードはない。
ステップ703では、同期ブロック(//Z07〜//Z12)に囲まれた中に、同期クラスから生成されるインスタンス変数htに関する参照メソッド呼び出しが2つ(ht.keys()とht.get())あり、同期ブロックをリード・ロック(read lock)で置き換える。さらに、htに関する更新メソッド呼び出し(ht.put())が//Z03にあるので、同期ブロックをライト・ロック(write lock)で置き換える。以上の変換の結果が、図8Cである。
図9は、スループット比、CPU使用率比及び性能向上比の各項目を示す。この性能比較のためのJava実行環境は、WebSphere Enterprise Service Bus 6.1(商標)及びJava Developers Kit(商標)を用い、SUN(商標)のNiagara2(商標)(64個のハードウェアスレッドを持つCPU)上で性能比較を実行した。
本発明の実施形態に係るコンピュータ・システム(1001)は、CPU(1002)とメイン・メモリ(1003)と含み、これらはバス(1004)に接続されている。CPU(1002)は好ましくは、32ビット又は64ビットのアーキテクチャに基づくものであり、例えば、インテル社のXeon(商標)シリーズ、Core(商標)シリーズ、Atom(商標)シリーズ、Pentium(商標)シリーズ、Celeron(商標)シリーズ、AMD社のPhenom(商標)シリーズ、Athlon(商標)シリーズ、Turion(商標)シリーズ及びSempron(商標)などを使用することができる。バス(1004)には、ディスプレイ・コントローラ(1005)を介して、LCDモニタなどのディスプレイ(1006)が接続されている。ディスプレイ(1006)は、コンピュータ・システムの管理のために、通信回線を介してネットワークに接続されたコンピュータ・システムについての情報と、そのコンピュータ・システム上で動作中のソフトウェアについての情報を、適当なグラフィック・インターフェースで表示するために使用される。バス(1004)にはまた、IDE又はSATAコントローラ(1007)を介して、ハードディスク又はシリコン・ディスク(1008)と、CD−ROM、DVDドライブ又はBlu−rayドライブ(1009)が接続されている。
請求項1及び15は、第1のプログラム・コードを第2のプログラム・コードに変換する方法の発明を記載する。請求項1及び15の発明は、例えば本発明の実施態様における図2によって実現される。
請求項2〜7は、上記変換の対象が第1のクラスである場合の変換の方法の発明を記載する。請求項2の発明は、例えば本発明の実施態様における図2のステップ206及びその詳細である図7Aによって実現される。請求項3の発明は、例えば本発明の実施態様における図2のステップ206及びその詳細である図7Aのステップ703によって実現される。請求項4〜6の発明は、例えば本発明の実施態様における図2のステップ206及びその詳細である図7Aのステップ703に含まれる各処理によって実現される。請求項7の発明は、例えば本発明の実施態様における図2のステップ206及びその詳細である図7Aのステップ702によって実現される。
請求項8〜14は、上記変換の対象が第2のクラスである場合の変換の方法の発明を記載する。請求項8の発明は、例えば本発明の実施態様における図2のステップ202及びその詳細である図3Aによって実現される。請求項9の発明は、例えば本発明の実施態様における図2のステップ202及びその詳細である図3Aのステップ305によって実現される。請求項10〜12の発明は、例えば本発明の実施態様における図2のステップ202及びその詳細である図3Aのステップ305の各処理によって実現される。請求項13の発明は、例えば本発明の実施態様における図2のステップ202及びその詳細である図3Aのステップ302によって実現される。請求項14の発明は、例えば本発明の実施態様における図2のステップ202及びその詳細である図3Aのステップ303によって実現される。
請求項16は、上記変換の対象がスレッド固有の値をキーとするメソッド呼び出しを含むクラスである場合の変換の方法の発明を記載する。請求項16の発明は、例えば本発明の実施態様における図2のステップ205によって実現される。
Claims (19)
- マルチスレッド上で動作するプログラムのプログラム・コード(以下、第1のプログラム・コード)をロック衝突が少ないプログラム・コード(以下、第2のプログラム・コード)に変換する方法であって、コンピュータが、
前記第1のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(以下、第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(以下、第2のクラス)が前記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
前記第1のプログラム・コードが前記第1のクラスを含むことに応じて、前記ロックによって同期を取りながら動作するクラス(以下、第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が前記第3のクラスよりも短い並行動作可能なクラス(以下、第4のクラス)のメソッド呼び出し(以下、第1のメソッド呼び出し)を含むところのクラスに変換するステップと、
前記第1のプログラム・コードが前記第2のクラスを含むことに応じて、前記親クラスのメソッド呼び出しを含む該第2のクラスを、前記親クラスに対応する機能を有し且つロックを獲得している区間が前記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(以下、第2のメソッド呼び出し)を含むところのクラスに変換するステップと
を実行することを含み、
A.前記第1のメソッド呼び出しを含むところのクラスに変換するステップが、
前記第1のクラスに含まれている前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記第3のクラスよりも短い並行動作可能な前記第1のメソッド呼び出しに変換するステップをさらに含み、
前記第1のメソッド呼び出しに変換するステップが、
(1)前記第1のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除するステップ、前記同期ブロックコードの位置を変更するステップ、又は前記同期ブロックコードに挟まれるコードを変更するステップ、又は、
(2)前記第1のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第1のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップ
をさらに含み、
B.前記第2のメソッド呼び出しを含むところのクラスに変換するステップが、
前記第2のクラスに含まれている前記親クラスのメソッド呼び出しを、前記親クラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記親クラスのメソッド呼び出しよりも短い並行動作可能な前記第2のメソッド呼び出しに変換するステップをさらに含み、
前記第2のメソッド呼び出しに変換するステップが、
(1)前記第2のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除するステップ、前記同期ブロックコードの位置を変更するステップ、又は前記同期ブロックコードに挟まれるコードを変更するステップ、
(2)前記第2のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第2のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップ、又は、
(3)前記親クラスで定義されているメソッドであって、前記第2のメソッド呼び出しを含むクラスで定義されていない該メソッドを、前記第2のメソッド呼び出しを含むクラスに前記親クラスと同じシグネチャで定義するステップと、
前記同じシグネチャで定義されたメソッドの実装を、前記親クラスで定義されているメソッドを呼び出すコードにするステップと
をさらに含む、前記方法。 - 前記A(1)の前記同期ブロックコードを削除するステップが、
前記同期ブロックコードに挟まれるコードに、前記第1のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項1に記載の方法。 - 前記A(1)の前記同期ブロックコードの位置を変更するステップが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
前記同期ブロックコードを削除するステップと、
前記パスを新たな同期ブロックコードで挟むステップと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む、請求項1に記載の方法。 - 前記A(1)の前記同期ブロックコードに挟まれるコードを変更するステップが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む、請求項1に記載の方法。 - 前記B(1)の前記同期ブロックコードを削除するステップが、
前記同期ブロックコードに挟まれるコードに、前記第2のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項1に記載の方法。 - 前記B(1)の前記同期ブロックコードの位置を変更するステップが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
前記同期ブロックコードを削除するステップと、
前記パスを新たな同期ブロックコードで挟むステップと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む、請求項1に記載の方法。 - 前記B(1)の前記同期ブロックコードに挟まれるコードを変更するステップが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む、請求項1に記載の方法。 - 前記コンピュータが、
スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含む前記第1のクラスが前記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
前記第1のプログラム・コードがスレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含むことに応じて、前記第1のクラスを、前記第3のクラスに対応する機能を有し且つ前記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
をさらに含む、請求項1に記載の方法。 - 前記スレッド・ローカルの値を使用するクラスに変換するステップが、
前記スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換するステップをさらに含む、請求項8に記載の方法。 - マルチスレッド上で動作するプログラムのプログラム・コード(以下、第1のプログラム・コード)をロック衝突が少ないプログラム・コード(以下、第2のプログラム・コード)に変換のためのコンピュータ・プログラムを実行するコンピュータ・システムであって、
前記第1のプログラム・コード及び前記変換のコンピュータ・プログラムを格納する記憶部と、
前記コンピュータ・プログラムを前記記憶部からメモリ内に読み出し、下記命令を実行する中央演算処理装置(CPU)であって、前記命令が、
前記第1のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(以下、第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(以下、第2のクラス)が前記第1のプログラム・コード中に含まれているかどうかを判定すること、
前記第1のプログラム・コードが前記第1のクラスを含むことに応じて、前記ロックによって同期を取りながら動作するクラス(以下、第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が前記第3のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(以下、第1のメソッド呼び出し)を含むところのクラスに変換すること、
前記第1のプログラム・コードが前記第2のクラスを含むことに応じて、前記親クラスのメソッド呼び出しを含む該第2のクラスを、前記親クラスに対応する機能を有し且つロックを獲得している区間が前記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(以下、第2のメソッド呼び出し)を含むところのクラスに変換すること
を含む、前記中央演算処理装置と
を含み、
A.前記第1のメソッド呼び出しを含むところのクラスに変換することが、
前記第1のクラスに含まれている前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記第3のクラスよりも短い並行動作可能な前記第1のメソッド呼び出しに変換することをさらに含み、
前記第1のメソッド呼び出しに変換することが、
(1)前記第1のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除すること、前記同期ブロックコードの位置を変更すること、又は前記同期ブロックコードに挟まれるコードを変更すること、又は、
(2)前記第1のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第1のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更すること
をさらに含み、
B.前記第2のメソッド呼び出しを含むところのクラスに変換することが、
前記第2のクラスに含まれている前記親クラスのメソッド呼び出しを、前記親クラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記親クラスのメソッド呼び出しよりも短い並行動作可能な前記第2のメソッド呼び出しに変換することをさらに含み、
前記第2のメソッド呼び出しに変換することが、
(1)前記第2のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除すること、前記同期ブロックコードの位置を変更すること、又は前記同期ブロックコードに挟まれるコードを変更すること、
(2)前記第2のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第2のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更すること、又は、
(3)前記親クラスで定義されているメソッドであって、前記第2のメソッド呼び出しを含むクラスで定義されていない該メソッドを、前記第2のメソッド呼び出しを含むクラスに前記親クラスと同じシグネチャで定義することと、
前記同じシグネチャで定義されたメソッドの実装を、前記親クラスで定義されているメソッドを呼び出すコードにすることと
をさらに含む、前記コンピュータ・システム。 - 前記A(1)の前記同期ブロックコードを削除することが、
前記同期ブロックコードに挟まれるコードに、前記第1のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項10に記載のコンピュータ・システム。 - 前記A(1)の前記同期ブロックコードの位置を変更することが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
前記同期ブロックコードを削除することと、
前記パスを新たな同期ブロックコードで挟むことと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加することと
を含む、請求項10に記載のコンピュータ・システム。 - 前記A(1)の前記同期ブロックコードに挟まれるコードを変更することが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えることと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更することと、
を含む、請求項10に記載のコンピュータ・システム。 - 前記B(1)の前記同期ブロックコードを削除することが、
前記同期ブロックコードに挟まれるコードに、前記第2のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項10に記載のコンピュータ・システム。 - 前記B(1)の前記同期ブロックコードの位置を変更することが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
前記同期ブロックコードを削除することと、
前記パスを新たな同期ブロックコードで挟むことと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加することと
を含む、請求項10に記載のコンピュータ・システム。 - 前記B(1)の前記同期ブロックコードに挟まれるコードを変更することが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えることと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更することと、
を含む、請求項10に記載のコンピュータ・システム。 - 前記コンピュータが、
スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含む前記第1のクラスが前記第1のプログラム・コード中に含まれているかどうかを判定することと、
前記第1のプログラム・コードがスレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含むことに応じて、前記第1のクラスを、前記第3のクラスに対応する機能を有し且つ前記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換することと
をさらに含む、請求項10に記載のコンピュータ・システム。 - 前記スレッド・ローカルの値を使用するクラスに変換することが、
前記スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換することをさらに含む、請求項17に記載のコンピュータ・システム。 - マルチスレッド上で動作するプログラムのプログラム・コード(以下、第1のプログラム・コード)をロック衝突が少ないプログラム・コード(以下、第2のプログラム・コード)に変換するコンピュータ・プログラムであって、コンピュータに、請求項1〜9のいずれか1項に記載の方法の各ステップを実行させる前記コンピュータ・プログラム。
Priority Applications (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2009052560A JP4754004B2 (ja) | 2009-03-05 | 2009-03-05 | マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム |
US12/715,874 US8572584B2 (en) | 2009-03-05 | 2010-03-02 | Converting program code of a multi-threaded program into program code causing less lock contentions |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2009052560A JP4754004B2 (ja) | 2009-03-05 | 2009-03-05 | マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム |
Publications (2)
Publication Number | Publication Date |
---|---|
JP2010205170A JP2010205170A (ja) | 2010-09-16 |
JP4754004B2 true JP4754004B2 (ja) | 2011-08-24 |
Family
ID=42679375
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
JP2009052560A Expired - Fee Related JP4754004B2 (ja) | 2009-03-05 | 2009-03-05 | マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム |
Country Status (2)
Country | Link |
---|---|
US (1) | US8572584B2 (ja) |
JP (1) | JP4754004B2 (ja) |
Families Citing this family (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US8402106B2 (en) * | 2010-04-14 | 2013-03-19 | Red Hat, Inc. | Asynchronous future based API |
WO2012164439A1 (en) | 2011-06-02 | 2012-12-06 | International Business Machines Corporation | Handling cross-thread method calls |
KR101620536B1 (ko) | 2012-08-01 | 2016-05-12 | 엠파이어 테크놀로지 디벨롭먼트 엘엘씨 | 액티브 록 정보 유지 및 검색 |
CN103049305B (zh) * | 2012-08-03 | 2017-03-08 | 北京航空航天大学 | 针对龙芯多核cpu模拟的动态代码转换的多线程化方法 |
CA2831134A1 (en) * | 2013-10-24 | 2015-04-24 | Ibm Canada Limited - Ibm Canada Limitee | Identification of code synchronization points |
US20220027146A1 (en) * | 2020-07-21 | 2022-01-27 | Salesforce.Com, Inc. | Method and system for updating configuration settings during the execution of an application |
CN115794356B (zh) * | 2023-01-31 | 2023-04-28 | 深圳方位通讯科技有限公司 | 基于ssh服务器的多线程同步连接处理方法 |
Family Cites Families (16)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US6119115A (en) * | 1998-03-12 | 2000-09-12 | Microsoft Corporation | Method and computer program product for reducing lock contention in a multiple instruction execution stream processing environment |
JP3756352B2 (ja) * | 1999-06-29 | 2006-03-15 | 富士通株式会社 | コンパイラ装置およびコンパイラを記録したコンピュータ読み取り可能な記録媒体 |
US6757891B1 (en) * | 2000-07-12 | 2004-06-29 | International Business Machines Corporation | Method and system for reducing the computing overhead associated with thread local objects |
US6851114B1 (en) * | 2000-11-06 | 2005-02-01 | Sun Microsystems, Inc. | Method for improving the performance of safe language multitasking |
US20040015912A1 (en) * | 2000-11-20 | 2004-01-22 | Bottomley Thomas Mark Walter | Method of byte code quickening: quick instructions for method invocation |
US6862664B2 (en) * | 2003-02-13 | 2005-03-01 | Sun Microsystems, Inc. | Method and apparatus for avoiding locks by speculatively executing critical sections |
CA2430383A1 (en) * | 2003-05-30 | 2004-11-30 | Ibm Canada Limited - Ibm Canada Limitee | Efficiently releasing locks when an exception occurs |
US7567963B2 (en) * | 2004-06-28 | 2009-07-28 | Intel Corporation | Thread synchronization with lock inflation methods and apparatus for managed run-time environments |
JP2006185232A (ja) * | 2004-12-28 | 2006-07-13 | Hitachi Ltd | 複数のプログラムの実行方法、プログラム変換方法及びこれを用いたコンパイラプログラム |
US8095921B2 (en) * | 2005-10-12 | 2012-01-10 | International Business Machines Corporation | Identifying code that wastes time switching tasks |
CA2539908A1 (en) * | 2006-03-16 | 2007-09-16 | Ibm Canada Limited - Ibm Canada Limitee | Lightweight single reader locks |
US7954094B2 (en) * | 2006-03-27 | 2011-05-31 | International Business Machines Corporation | Method for improving performance of executable code |
US8176491B1 (en) * | 2006-08-04 | 2012-05-08 | Oracle America, Inc. | Fast synchronization of simple synchronized methods |
JP2008257594A (ja) * | 2007-04-06 | 2008-10-23 | Hitachi Ltd | 情報処理装置および情報処理方法 |
US8266607B2 (en) * | 2007-08-27 | 2012-09-11 | International Business Machines Corporation | Lock reservation using cooperative multithreading and lightweight single reader reserved locks |
US7908256B2 (en) * | 2007-11-30 | 2011-03-15 | International Business Machines Corporation | Speculative computation lock coarsening through the use of localized lock reservation |
-
2009
- 2009-03-05 JP JP2009052560A patent/JP4754004B2/ja not_active Expired - Fee Related
-
2010
- 2010-03-02 US US12/715,874 patent/US8572584B2/en not_active Expired - Fee Related
Also Published As
Publication number | Publication date |
---|---|
JP2010205170A (ja) | 2010-09-16 |
US20100229160A1 (en) | 2010-09-09 |
US8572584B2 (en) | 2013-10-29 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
JP4754004B2 (ja) | マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム | |
Schäling | The boost C++ libraries | |
Pulte et al. | Promising-ARM/RISC-V: a simpler and faster operational concurrency model | |
JP5851396B2 (ja) | 処理方法 | |
TWI442235B (zh) | 記憶體交易群組 | |
US8141035B2 (en) | Method for accessing internal states of objects in object oriented programming | |
US20160232017A1 (en) | System and Method for Reloading Constructors | |
JP2000507373A (ja) | インタラクティブソフトウェア開発システム | |
JP5204300B2 (ja) | マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム | |
US20160034276A1 (en) | Adaptive interface for cross-platform component generation | |
US9367429B2 (en) | Diagnostics of declarative source elements | |
US8595175B2 (en) | Fluent API patterns for managing object persistence | |
Zardoshti et al. | Simplifying transactional memory support in c++ | |
US8606766B2 (en) | Method and system to handle java class versioning | |
US9766926B2 (en) | Method and system for optimizing parallel program execution based on speculation that an object written to is not shared | |
Cho et al. | Sequential reasoning for optimizing compilers under weak memory concurrency | |
Gu et al. | Automating object transformations for dynamic software updating via online execution synthesis | |
US7823141B1 (en) | Using a concurrent partial inspector loop with speculative parallelism | |
Rigo et al. | Atomic Instruction Translation Towards A Multi-Threaded QEMU. | |
CN101689136B (zh) | 事务存储器的对象模型 | |
JP5276094B2 (ja) | トランザクション・メモリ・システムにおけるトランザクション・コード・ブロックを効果的に検索する方法 | |
Honorio et al. | On the efficiency of transactional code generation: A GCC case study | |
TWI467491B (zh) | 用於使用協調物件之修正式電腦結構之方法、系統與電腦程式產品 | |
Vysocký et al. | Application instrumentation for performance analysis and tuning with focus on energy efficiency | |
Ma et al. | Efficient Scheduler Live Update for Linux Kernel with Modularization |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
A621 | Written request for application examination |
Free format text: JAPANESE INTERMEDIATE CODE: A621 Effective date: 20101125 |
|
A977 | Report on retrieval |
Free format text: JAPANESE INTERMEDIATE CODE: A971007 Effective date: 20110407 |
|
A131 | Notification of reasons for refusal |
Free format text: JAPANESE INTERMEDIATE CODE: A131 Effective date: 20110412 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20110418 Free format text: JAPANESE INTERMEDIATE CODE: A821 Effective date: 20110418 |
|
TRDD | Decision of grant or rejection written | ||
A01 | Written decision to grant a patent or to grant a registration (utility model) |
Free format text: JAPANESE INTERMEDIATE CODE: A01 Effective date: 20110511 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A821 Effective date: 20110511 |
|
RD14 | Notification of resignation of power of sub attorney |
Free format text: JAPANESE INTERMEDIATE CODE: A7434 Effective date: 20110511 |
|
A01 | Written decision to grant a patent or to grant a registration (utility model) |
Free format text: JAPANESE INTERMEDIATE CODE: A01 |
|
A61 | First payment of annual fees (during grant procedure) |
Free format text: JAPANESE INTERMEDIATE CODE: A61 Effective date: 20110524 |
|
FPAY | Renewal fee payment (event date is renewal date of database) |
Free format text: PAYMENT UNTIL: 20140603 Year of fee payment: 3 |
|
R150 | Certificate of patent or registration of utility model |
Free format text: JAPANESE INTERMEDIATE CODE: R150 |
|
LAPS | Cancellation because of no payment of annual fees |