(57)【要約】【課題】ロック衝突による性能低下の問題があらかじめ発生しそうな箇所を自動的に特定し、該箇所を自動的に修正する方法が必要とされている。【解決手段】本発明は、マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換する方法、並びにそのコンピュータ・プログラム及びコンピュータ・システムを提供する。【選択図】図１
2010205170.tif 000002
【特許請求の範囲】
【請求項１】
マルチスレッド上で動作するプログラムのプログラム・コード（以下、第１のプログラム・コード）をロック衝突が少ないプログラム・コード（以下、第２のプログラム・コード）に変換する方法であって、
前記第１のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス（以下、第１のクラス）又はロックによって同期を取りながら動作する親クラスを継承しているクラス（以下、第２のクラス）が前記第１のプログラム・コード中に含まれているかどうかを判定するステップと、
前記第１のプログラム・コードが前記第１のクラスを含むことに応じて、前記ロックによって同期を取りながら動作するクラス（以下、第３のクラス）のメソッド呼び出しを含む該第１のクラスを、該第３のクラスに対応する機能を有し且つロックを獲得している区間が前記第３のクラスよりも短い並行動作可能なクラス（以下、第４のクラス）のメソッド呼び出し（以下、第１のメソッド呼び出し）を含むところのクラスに変換するステップと、
前記第１のプログラム・コードが前記第２のクラスを含むことに応じて、前記親クラスのメソッド呼び出しを含む該第２のクラスを、前記親クラスに対応する機能を有し且つロックを獲得している区間が前記第２のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（以下、第２のメソッド呼び出し）を含むところのクラスに変換するステップと
を含む、前記方法。
【請求項２】
前記第１のメソッド呼び出しを含むクラスに変換するステップが、
前記第１のクラスに含まれている前記第３のクラスのメソッド呼び出しを、前記第３のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記第３のクラスよりも短い並行動作可能な前記第１のメソッド呼び出しに変換するステップをさらに含む、請求項１に記載の方法。
【請求項３】
前記第１のメソッド呼び出しに変換するステップが、
前記第１のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除するステップ、前記同期ブロックコードの位置を変更するステップ、又は前記同期ブロックコードに挟まれるコードを変更するステップをさらに含む、請求項２に記載の方法。
【請求項４】
前記同期ブロックコードを削除するステップが、
前記同期ブロックコードに挟まれるコードに、前記第１のメソッド呼び出しが１つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも１が含まれていない場合に行われる、請求項３に記載の方法。
【請求項５】
前記同期ブロックコードの位置を変更するステップが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第１のメソッド呼び出しと、該第１のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを２以上含む場合、
前記同期ブロックコードを削除するステップと、
前記パスを新たな同期ブロックコードで挟むステップと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第１のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む、請求項３に記載の方法。
【請求項６】
前記同期ブロックコードに挟まれるコードを変更するステップが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第１のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される２つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む、請求項３に記載の方法。
【請求項７】
前記第１のメソッド呼び出しに変換するステップが、
前記第１のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第１のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む、請求項２に記載の方法。
【請求項８】
前記第２のメソッド呼び出しを含むクラスに変換するステップが、
前記第２のクラスに含まれている前記親クラスのメソッド呼び出しを、前記親クラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記親クラスのメソッド呼び出しよりも短い並行動作可能な前記第２のメソッド呼び出しに変換するステップをさらに含む、請求項１に記載の方法。
【請求項９】
前記第２のメソッド呼び出しに変換するステップが、
前記第２のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除するステップ、前記同期ブロックコードの位置を変更するステップ、又は前記同期ブロックコードに挟まれるコードを変更するステップをさらに含む、請求項８に記載の方法。
【請求項１０】
前記同期ブロックコードを削除するステップが、
前記同期ブロックコードに挟まれるコードに、前記第２のメソッド呼び出しが１つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも１が含まれていない場合に行われる、請求項９に記載の方法。
【請求項１１】
前記同期ブロックコードの位置を変更するステップが、
前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第２のメソッド呼び出しと、該第２のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを２以上含む場合、
前記同期ブロックコードを削除するステップと、
前記パスを新たな同期ブロックコードで挟むステップと、
前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第２のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む、請求項９に記載の方法。
【請求項１２】
前記同期ブロックコードに挟まれるコードを変更するステップが、
前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第２のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される２つ以上の読み出しを含む場合、
前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む、請求項９に記載の方法。
【請求項１３】
前記第２のメソッド呼び出しに変換するステップが、
前記第２のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、前記第２のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む、請求項８に記載の方法。
【請求項１４】
前記第２のメソッド呼び出しに変換するステップが、
前記親クラスで定義されているメソッドであって、前記第２のメソッド呼び出しを含むクラスで定義されていない該メソッドを、前記第２のメソッド呼び出しを含むクラスに前記親クラスと同じシグネチャで定義するステップと、
前記同じシグネチャで定義されたメソッドの実装を、前記親クラスで定義されているメソッドを呼び出すコードにするステップと
をさらに含む、請求項９に記載の方法。
【請求項１５】
スレッド固有の値をキーとする前記第３のクラスのメソッド呼び出しを含む前記第１のクラスが前記第１のプログラム・コード中に含まれているかどうかを判定するステップと、
前記第１のプログラム・コードがスレッド固有の値をキーとする前記第３のクラスのメソッド呼び出しを含むことに応じて、前記第１のクラスを、前記第３のクラスに対応する機能を有し且つ前記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
をさらに含む、請求項１に記載の方法。
【請求項１６】
前記スレッド・ローカルの値を使用するクラスに変換するステップが、
前記スレッド固有の値をキーとする前記第３のクラスのメソッド呼び出しを、前記第３のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換するステップをさらに含む、請求項１５に記載の方法。
【請求項１７】
マルチスレッド上で動作するプログラムのプログラム・コード（以下、第１のプログラム・コード）をロック衝突が少ないプログラム・コード（以下、第２のプログラム・コード）に変換のためのコンピュータ・プログラムを実行するコンピュータ・システムであって、
前記第１のプログラム・コード及び前記変換のコンピュータ・プログラムを格納する記憶部と、
前記コンピュータ・プログラムを前記記憶部からメモリ内に読み出し、下記命令を実行する中央演算処理装置（ＣＰＵ）であって、該命令が下記命令を含み、該命令が、
ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス（以下、第１のクラス）又はロックによって同期を取りながら動作する親クラスを継承しているクラス（以下、第２のクラス）が前記第１のプログラム・コード中に含まれているかどうかを判定すること、
前記第１のプログラム・コードが前記第１のクラスを含むことに応じて、前記ロックによって同期を取りながら動作するクラス（以下、第３のクラス）のメソッド呼び出しを含む該第１のクラスを、該第３のクラスに対応する機能を有し且つロックを獲得している区間が前記第３のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（以下、第１のメソッド呼び出し）を含むところのクラスに変換すること、
前記第１のプログラム・コードが前記第２のクラスを含むことに応じて、前記親クラスのメソッド呼び出しを含む該第２のクラスを、前記親クラスに対応する機能を有し且つロックを獲得している区間が前記第２のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（以下、第２のメソッド呼び出し）を含むところのクラスに変換すること
を含む、前記中央演算処理装置と
を含む、前記コンピュータ・システム。
【請求項１８】
前記第１のメソッド呼び出しを含むクラスに変換することが、
前記第１のクラスに含まれている前記第３のクラスのメソッド呼び出しを、前記第３のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が前記第３のクラスよりも短い並行動作可能な前記第１のメソッド呼び出しに変換することをさらに含む、請求項１７に記載の方法。
【請求項１９】
前記第１のメソッド呼び出しを含むクラスに変換することが、
前記第１のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、前記同期ブロックコードを削除すること、前記同期ブロックコードの位置を変更すること、又は前記同期ブロックコードに挟まれるコードを変更することをさらに含む、請求項１８に記載のコンピュータ・システム。
【請求項２０】
コンピュータに、請求項１〜１６のいずれか１項に記載の方法の各ステップを実行させるコンピュータ・プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システムに関する。
【背景技術】
【０００２】
近年、プロセッサ・アーキテクチャにおいて、１つの中央演算処理装置（以下、ＣＰＵ：Central Processing Unit）の内部に複数のＣＰＵコアを封入したいわゆるマルチコアへのシフトが進んでいる。マルチコアは、外部的には１つのＣＰＵでありながら、内部的には２つのＣＰＵとして認識させられるので、主に並列処理を行わせる環境下において、ＣＰＵチップ全体での処理能力を上げ、性能向上を果たすことが可能である。マルチコアは、プロセッサが同時に実行可能なハードウェアスレッドの数を飛躍的に増加させる。例えば、ＳＵＮ（商標）のNiagara２（商標）は、１ＣＰＵ上で６４個のスレッドを実行することが可能である。
【０００３】
このように、複数のスレッドを同時に実行することが可能なプロセッサ上で従来のプログラムが実行される場合、ロック衝突によるプロセッサの性能低下が問題になる。ここで、ロック衝突とは、スレッドが、排他実行が必要なクリティカル・セクションに入る際にロックを獲得した場合、他のスレッドは、そのロックが解除されるまで次のステップに進めない状態をいう。次のステップに進めないスレッドは、典型的には、スピン・ループ（spin loop）又はスリープ（sleep）状態になる。
【０００４】
ロック衝突が発生する原因はさまざまである。原因の１つは、プログラム・コードが、スレッドの排他実行のためにロックの獲得及び解放を行いながら動作する、いわゆるコレクション（Collection）クラス（以下、「同期コレクション・クラス」という）を使用する場合がである。該プログラム・コードは、例えば、この同期コレクション・クラスに属し、所与のキーから値への対応付けを行うマップ（Map）クラス（以下、「同期マップ・クラス」という）へアクセスするコードである。該プログラム・コードでは、同期マップ・クラスに含まれている全てのメソッドが、該同期マップ・クラスのインスタンス・オブジェクトによってロックされる。そのために、複数のスレッドが同じ同期マップ・クラスにアクセスしようすると、ロック衝突が頻繁に発生する。ロック衝突が発生すると、プロセッサは、１つのスレッドしか同時に実行できない。よって、ロック衝突は、性能上のスケーラビリティの問題を引き起こす。例えば、ＳＵＮ（商標）のNiagara2（商標）上では、ロック衝突によってＣＰＵが６０％程度しか使用されなくなる。
【０００５】
下記非特許文献１は、上記同期コレクション・クラスの例であるハッシュ表クラス（Hashtable）を、同期を取らずに並行動作可能な並行ハッシュマップ・クラス（ConcurrentHashMap）に置き換えることができることを記載する。並行ハッシュマップ・クラスの詳細については、下記非特許文献２を参照されたい。
【０００６】
また、ハッシュ表クラスの使用を並行ハッシュマップ・クラスの使用に変換するために、コード中の「Hashtable」を、エディタに付属する置換機能で「ConcurrentHashMap」に単純に置換した場合、（１）同期マップ・クラス（Synchronized map class）のメソッドが、同期ブロック（synchronized block）で囲まれている場合、（２）クラスが、ハッシュ表クラス（java.util.Hashtable）を継承している場合、（３）同期マップ・クラスのキー（key）をスレッド固有の値で利用している場合、ロック衝突を減らすことができない。このような問題が生じることは、Websphere Enterprise Service Bus（商標）や Java Developers Kit（商標）のクラス内で確認されている。
【先行技術文献】
【非特許文献】
【０００７】
【非特許文献１】Brian Gortz、“Java theory and practice: Concurrent collections classes”、2003年7月23日、インターネット（ＵＲＬ：http://www.ibm.com/developerworks/java/library/j-jtp07233.html?S_TACT=105AG）
【非特許文献２】Java(TM) 2 Platform Standard Ed. 5.0、“ConcurrentHashMap(Java 2 Platform SE 5.0) “インターネット（ＵＲＬ：http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html）
【発明の概要】
【発明が解決しようとする課題】
【０００８】
ロック衝突による性能低下の問題が発生するたびに、原因を特定し、人手でプログラム・コードを修正する作業が必要である。しかし、該作業は、現存するプログラム・コードの量から考えると、多量のワークロードを必要とするので不可能に近い。従って、上記問題があらかじめ発生しそうな箇所を自動的に特定し、該箇所を自動的に修正する方法が必要とされている。
しかし、非特許文献１は、ハッシュ表クラスを並行ハッシュマップ・クラスに自動的に置き換えるアルゴリズムを記載していない。
また、上記で述べた、ハッシュ表クラスの使用を並行ハッシュマップ・クラスの使用に変換するにあたってロック衝突の問題に対応するために、同期マップ・クラスを自動的に置き換えるアルゴリズムを用意する必要がある。
【課題を解決するための手段】
【０００９】
本発明は、マルチスレッド上で動作するプログラムのプログラム・コード（以下、第１のプログラム・コード）をロック衝突が少ないプログラム・コード（以下、第２のプログラム・コード）に変換する方法を提供する。該方法は、コンピュータ・システムに下記ステップを実行させる。該ステップは、
上記第１のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス（以下、第１のクラス）又はロックによって同期を取りながら動作する親クラスを継承しているクラス（以下、第２のクラス）が上記第１のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第１のプログラム・コードが上記第１のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス（以下、第３のクラス）のメソッド呼び出しを含む該第１のクラスを、該第３のクラスに対応する機能を有し且つロックを獲得している区間が上記第３のクラスよりも短い並行動作可能なクラス（以下、第４のクラス）のメソッド呼び出し（以下、第１のメソッド呼び出し）を含むところのクラスに変換するステップと、
上記第１のプログラム・コードが上記第２のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第２のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第２のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（以下、第２のメソッド呼び出し）を含むところのクラスに変換するステップと
を含む。
【００１０】
本発明はさらに、マルチスレッド上で動作するプログラムのプログラム・コード（第１のプログラム・コード）をロック衝突が少ないプログラム・コード（第２のプログラム・コード）に変換のためのコンピュータ・プログラムを実行するコンピュータ・システムを提供する。該コンピュータ・システムは、
上記第１のプログラム・コード及び上記変換のコンピュータ・プログラムを格納する記憶部と、
上記コンピュータ・プログラムを上記記憶部からメモリ内に読み出し、下記命令を実行する中央演算処理装置（ＣＰＵ）であって、該命令が下記命令を含み、該命令が、
ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス（第１のクラス）又はロックによって同期を取りながら動作する親クラスを継承しているクラス（第２のクラス）が上記第１のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第１のプログラム・コードが上記第１のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス（第３のクラス）のメソッド呼び出しを含む該第１のクラスを、該第３のクラスに対応する機能を有し且つロックを獲得している区間が記第３のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（第１のメソッド呼び出し）を含むところのクラスに変換するステップと、
上記第１のプログラム・コードが上記第２のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第２のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第２のクラスよりも短い並行動作可能なクラスのメソッド呼び出し（第２のメソッド呼び出し）を含むところのクラスに変換するステップと
を含む。
【００１１】
本発明の１つの実施態様では、上記第１のメソッド呼び出しを含むクラスに変換するステップが、上記第１のクラスに含まれている上記第３のクラスのメソッド呼び出しを、上記第３のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が上記第３のクラスよりも短い並行動作可能な上記第１のメソッド呼び出しに変換するステップをさらに含む。
【００１２】
本発明の１つの実施態様では、上記第１のメソッド呼び出しに変換するステップが、上記第１のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、上記同期ブロックコードを削除するステップ、上記同期ブロックコードの位置を変更するステップ、又は上記同期ブロックコードに挟まれるコードを変更するステップをさらに含む。
【００１３】
本発明の１つの実施態様では、上記同期ブロックコードを削除するステップが、上記同期ブロックコードに挟まれるコードに、上記第１のメソッド呼び出しが１つ含まれるか又は含まれず、且つ、上記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも１が含まれていない場合に行われる。
【００１４】
本発明の１つの実施態様では、上記同期ブロックコードの位置を変更するステップが、
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第１のメソッド呼び出しと、該第１のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを２以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第１のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
【００１５】
本発明の１つの実施態様では、上記同期ブロックコードに挟まれるコードを変更するステップが、
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第１のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される２つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
【００１６】
本発明の１つの実施態様では、上記第１のメソッド呼び出しに変換するステップが、上記第１のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、上記第１のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む。
【００１７】
本発明の１つの実施態様では、上記第２のメソッド呼び出しを含むクラスに変換するステップが、上記第２のクラスに含まれている上記親クラスのメソッド呼び出しを、上記親クラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が上記親クラスのメソッド呼び出しよりも短い並行動作可能な上記第２のメソッド呼び出しに変換するステップをさらに含む。
【００１８】
本発明の１つの実施態様では、上記第２のメソッド呼び出しに変換するステップが、上記第２のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、上記同期ブロックコードを削除するステップ、上記同期ブロックコードの位置を変更するステップ、又は上記同期ブロックコードに挟まれるコードを変更するステップをさらに含む。
【００１９】
本発明の１つの実施態様では、上記同期ブロックコードを削除するステップが、上記同期ブロックコードに挟まれるコードに、上記第２のメソッド呼び出しが１つ含まれるか又は含まれず、且つ、上記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも１が含まれていない場合に行われる。
【００２０】
本発明の１つの実施態様では、上記同期ブロックコードの位置を変更するステップが、
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第２のメソッド呼び出しと、該第２のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを２以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第２のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
【００２１】
本発明の１つの実施態様では、上記同期ブロックコードに挟まれるコードを変更するステップが、
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第２のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される２つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
【００２２】
本発明の１つの実施態様では、上記第２のメソッド呼び出しに変換するステップが、上記第２のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、上記第２のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む。
【００２３】
本発明の１つの実施態様では、上記第２のメソッド呼び出しに変換するステップが、
上記親クラスで定義されているメソッドであって、上記第２のメソッド呼び出しを含むクラスで定義されていない該メソッドを、上記第２のメソッド呼び出しを含むクラスに上記親クラスと同じシグネチャで定義するステップと、
上記同じシグネチャで定義されたメソッドの実装を、上記親クラスで定義されているメソッドを呼び出すコードにするステップと
をさらに含む。
【００２４】
本発明の１つの実施態様では、上記方法は、コンピュータ・システムに下記ステップをさらに実行させる。該ステップは、
スレッド固有の値をキーとする上記第３のクラスのメソッド呼び出しを含む上記第１のクラスが上記第１のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第１のプログラム・コードがスレッド固有の値をキーとする上記第３のクラスのメソッド呼び出しを含むことに応じて、上記第１のクラスを、上記第３のクラスに対応する機能を有し且つ上記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
を含む。
【００２５】
本発明の１つの実施態様では、上記スレッド・ローカルの値を使用するクラスに変換するステップが、上記スレッド固有の値をキーとする上記第３のクラスのメソッド呼び出しを、上記第３のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換するステップをさらに含む。
【００２６】
本発明はさらに、コンピュータに、上記方法のいずれか１つに記載の方法の各ステップを実行させるコンピュータ・プログラムを提供する。
【発明の効果】
【００２７】
本発明の実施態様によれば、ロックによって同期を取るクラスにアクセスするプログラム・コードが、ロックを獲得している区間が上記ロックによって同期を取るクラスよりも短い並行動作可能なクラスにアクセスするプログラム・コードに自動的に変換される。さらに、該変換では、プログラム・コード上の同期ブロックによってロックされる範囲が自動的に狭められる。上記変換により、プログラム・コード実行時のロック衝突時間が減少し、マルチスレッド上のＣＰＵ効率の低下を防止することが可能である。
【図面の簡単な説明】
【００２８】
【図１】本発明の実施態様における、プログラム・コードを変換するためのシステムが有する機能を図示する機能ブロック図を示す。
【図２】本発明の実施態様における、図１に示すメモリ内にある第１のＪａｖａコードを第２のＪａｖａコードに変換する処理フローの概要を示す。
【図３Ａ】本発明の実施態様における、図２のステップ２０２における処理の詳細フローを示す。
【図３Ｂ】本発明の実施態様における、図３Ａのステップ３０４における処理の詳細フローを示す。
【図３Ｃ】本発明の実施態様における、図３Ａのステップ３０４における処理の詳細フローを示す。
【図３Ｄ】本発明の実施態様における、図３Ａのステップ３０４における処理の詳細フローを示す。
【図３Ｅ】本発明の実施態様における、図３Ａのステップ３０４における処理の詳細フローを示す。
【図３Ｆ】本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下でＳＢ１を除去する処理のフローを示す。
【図３Ｇ】本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
【図３Ｈ】本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図３Ｉ】本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図３Ｊ】本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図４Ａ】本発明の実施態様における、図３Ａのステップ３０４におけるコード変換の例を示す。
【図４Ｂ】本発明の実施態様における、図１に示すメモリ内にある第１のＪａｖａコードであるＣＬ（クラスＸ）を示す。
【図４Ｃ】本発明の実施態様における、図１に示すメモリ内にある第２のＪａｖａコードであるＣＬ（クラスＸ）を示す。
【図５Ａ】本発明の実施態様における、図２のステップ２０５の詳細フローを示す。
【図５Ｂ】本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下でＳＢ１を除去する処理のフローを示す。
【図５Ｃ】本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
【図５Ｄ】本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図５Ｅ】本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図５Ｆ】本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図６Ａ】本発明の実施態様における、図１に示すメモリ内にある第１のＪａｖａコードであるＣＬ（クラスＹ）を示す。
【図６Ｂ】本発明の実施態様における、図１に示すメモリ内にある第２のＪａｖａコードであるＣＬ（クラスＹ）を示す。
【図７Ａ】本発明の実施態様における、図２のステップ２０６の詳細フローを示す。
【図７Ｂ】本発明の実施態様における、図７Ａのステップ７０２における処理の詳細フローを示す。
【図７Ｃ】本発明の実施態様における、図７Ａのステップ７０２における処理の詳細フローを示す。
【図７Ｄ】本発明の実施態様における、図７Ａのステップ７０２における処理の詳細フローを示す。
【図７Ｅ】本発明の実施態様における、図７Ａのステップ７０２における処理の詳細フローを示す。
【図７Ｆ】本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下でＳＢ１を除去する処理のフローを示す。
【図７Ｇ】本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
【図７Ｈ】本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図７Ｉ】本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図７Ｊ】本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。
【図８Ａ】本発明の実施態様における、図７Ａのステップ７０２におけるコード変換の例である。
【図８Ｂ】本発明の実施態様における、図１に示すメモリ内にある変換前の第１のＪａｖａコードであるＣＬ（クラスＺ）を示す。
【図８Ｃ】本発明の実施態様における、図１に示すメモリ内にある変換後の第２のＪａｖａコードであるＣＬ（クラスＺ）を示す。
【図９】コード変換の適用前と、本発明の実施態様におけるコード変換の適用後との性能比較の結果の一例を示す。
【図１０】本発明の実施態様における、図１のシステムが有するコンピュータ・ハードウェアのブロック図を示す。
【図１１】特許請求の範囲に記載の発明の理解を容易にするための図を示す。
【発明を実施するための形態】
【００２９】
以下に本明細書及び特許請求の範囲で用いている語について説明をする。
【００３０】
本発明の実施態様において、「マルチスレッド上で動作するプログラムのプログラム・コード」とは、スレッドと呼ばれる処理単位を複数生成し、スレッド毎にＣＰＵタイムを割り当てることで、並行して複数の処理を行なうことができるプログラムのソースコードをいう。該ソースコードは、例えばＪａｖａ（商標）言語又はＣ言語（例えばＣ＋＋）を使用して記述される。
【００３１】
本発明の実施態様において、「ロックによって同期を取りながら」とは、スレッド上で実行される処理がクリティカル・セクションに入り、共有データの読み書きを行う場合、ロックを獲得し又は解放することによって、排他制御を行うことをいう。クリティカル・セクションとは、コンピュータ上において、単一のリソースに対して複数の処理が同時期に実行されると破綻をきたす部分をいう。
【００３２】
本発明の実施態様において、「ロック衝突」とは、１つのスレッド上で実行される処理がクリティカル・セクションに入り、共有データの読み書きを行うためにロックを獲得すると、該ロックが解放されるまでは、他のスレッド上で実行される処理がロックを獲得できず実行待ちになる状態をいう。
【００３３】
本発明の実施態様において、「ロック衝突が少ない」とは、ロック衝突の頻度それ自身が減少する場合と、ロック衝突が発生したとしてもロック獲得からロック開放までの時間が短く、結果として他のスレッドのロック待ち、すなわちロック衝突の発生している時間が短くなる場合とを含む。ロック衝突の頻度それ自身が減少する場合とは、データ構造の工夫等によりロック機構を使わないで並行動作を可能にする場合を含む。ロック衝突が発生したとしてロック獲得からロック開放までの時間が短くなることを、ロックスコープが減少するともいう。
【００３４】
本発明の実施態様において、「ロックによって同期を取りながら動作するクラス」とは、ロックの獲得・解放によって同期を取りながらデータにアクセスするクラス又はインタフェース（以下、クラスという）である。本発明の実施態様では、上記クラスの一種であり、マップ（Ｍａｐ）インタフェース（キーから高々１つの値への対応付け（マッピング）を行う）を実装するクラスを、同期マップ・クラス（synchronized map class）という。同期マップ・クラスは、具体例ではハッシュ表クラス（java.util.Hashtable）、又はコレクション・クラスの同期マップメソッド（java.util.Collections.synchronizedMap()）でラップされたマップ・クラス（java.util.Map）である。
【００３５】
本発明の実施態様において、「並行動作可能なクラス」とは、ロックによって同期動作をするクラスと同じ機能を有し、且つ、ロックを獲得している区間がロックによって同期動作をするクラスよりも短い並行（concurrent）に実行可能なクラスをいう。「並行動作可能なクラス」は、例えばクラス・ライブラリに予め用意されている。
ここで「並行動作可能」とは、ロック衝突が少なく且つ安全にマルチスレッドが実行可能なことである。並行動作可能とは、具体的には、メソッドget()等の取得動作、メソッドput()又はメソッドremove()等の更新操作、及びメソッドputAll又はメソッドclear()等の集計操作によるロック衝突が少なく、且つ、ロックを獲得しないインタフェースIterators/Enumerationsの反復/列挙操作の操作中にConcurrentModificationException等の例外が発生しないことを意味する。並行動作可能なクラスは、例えばハッシュ表クラスに対応する並行ハッシュマップ・クラス（java.util.concurrent.ConcurrentHashMap）及び同期マップ・クラスに対応する並行マップ・クラス（concurrent map class）が該当しうる。なお、並行マップ・クラスには、clone()メソッドなどの固有のメソッドの定義が存在するが、並行ハッシュマップ・クラスには、上記固有のメソッドの定義は含まれない。
【００３６】
本発明の実施態様において、「ロックを獲得している区間」とは、プログラム・コード上の、ロックを獲得する命令とロックを開放する命令との間のコード部分をいう。上記区間は、例えば、同期ブロックで囲まれるコード部分である。
【００３７】
以下、図面に従って、本発明の実施態様を説明する。本実施態様は、本発明の好適な態様を説明するためのものであり、本発明の範囲をここで示すものに限定する意図はないことを理解されたい。また、以下の図を通して、特に断らない限り、同一の符号は、同一の対象を指す。
【００３８】
図１は、本発明の実施態様における、プログラム・コードを変換するためのシステムが有する機能を図示する機能ブロック図を示す。
コンピュータ・システム（１００）は、典型的には、ＣＰＵ（１０１）、メモリ（１０２）、及び記憶部（１０３）を含む。コンピュータ・システム（１００）はまた、入出力部（１０４）及び通信部（１０５）を含んでいてもよい。
コンピュータ・システム（１００）は、本発明のＪａｖａコードを変換するためのプログラム（１０６）（以下、変換用プログラム）、該変換用プログラムに従い変換されるプログラム、例えばＪａｖａコード（１０８）（以下、第１のＪａｖａコード）及び、変換において参照される対応テーブル（１０７）を記憶部（１０３）に含む。以下では、変換用プログラムに従い変換されるプログラムがＪａｖａコードである場合を例として説明するが、他のプログラムについても同様に適用することが可能である。
第１のＪａｖａコード（１０８）は、該コンピュータ・システム（１００）の入出力部（１０４）を介して、又はネットワークを経由して通信部（１０５）から記憶部（１０３）に格納されてもよい。ＣＰＵ（１０１）は、変換用プログラム（１０６）を記憶部（１０３）からメモリ（１０２）内に読み込む。ＣＰＵ（１０１）は、該変換用プログラム（１０６）の命令を実行し、第１のＪａｖａコード（１０８）及び対応テーブル（１０７）を記憶部（１０３）からメモリ（１０２）内に読み込み、該読み込んだ第１のＪａｖａコード（１０８）を、ロック衝突の少ないＪａｖａコード（１１０）（以下、第２のＪａｖａコード）に変換する。第１のＪａｖａコードから第２のＪａｖａコードへの変換において、変換途中のＪａｖａコード（１０９）を経てもよい。
【００３９】
本発明の実施態様では、第１のＪａｖａコード（１０８）中で同期マップ・クラスが使われている場合に、コンピュータ・システム（１００）は、対応テーブル（１０７）及び／又は変換用プログラム（１０６）にあらかじめ用意された対応を用いて、該同期マップ・クラスを上記同期マップ・クラスに対応する並行マップ・クラスに自動的に置き換える。該置き換えにより、Ｊａｖａコード実行時のロック衝突が減少する。
対応テーブル（１０７）は、同期マップ・クラスと並行マップ・クラスとの対応が保存されたテーブルである。対応テーブル（１０７）には、例えば、同期マップ・クラスのアプリケーション・プログラム・インターフェース（ＡＰＩ）と、上記同期マップ・クラスのＡＰＩと同じ機能を提供する並行マップ・クラスのＡＰＩであって、ロックを獲得している区間が上記同期マップ・クラスより短い並行動作可能な上記ＡＰＩとの組が保存される。コンピュータ・システム（１００）は、第１のＪａｖａコード（１０８）中で同期マップ・クラスのＡＰＩが使われている場合に、同期マップ・クラスのＡＰＩと組をなす並行マップ・クラスのＡＰＩを対応テーブル（１０７）から求める。これによりコンピュータ・システム（１００）は、同期マップ・クラスのＡＰＩを、該求めた並行マップ・クラスのＡＰＩに置き換えることができる。
【００４０】
第１のＪａｖａコード（１０８）が、以下の３種類のクラスのうちのいずれか１つを含む場合に、上記置き換えが可能である。
１．同期マップ・クラスが利用されているクラス
２．同期を取ることが明記されているコレクション・クラスを継承したクラス
同期をとることが明記されているコレクション・クラスとは、例えば、Ｊａｖａクラス・ライブラリの同期ハッシュ表クラス（java.util.Hashtable）、Ｊａｖａクラス・ライブラリの同期ベクトルクラス（java.util.Vector）及びＪａｖａクラス・ライブラリの同期スタッククラス（java.util.Stack）である。
本明細書では、同期をとることが明記されているコレクション・クラスを上記同期ハッシュ表クラスとし、上記同期ハッシュ表クラスに対応する並行マップ・クラスを並行ハッシュ表クラス（concurrentHashtable）として説明する。
従って、同期ハッシュ表クラスを継承したクラスを用いた実施態様（図２のステップ２０２及び図３Ａ〜図３Ｉの全てのステップ）は、同期を取ることが明記されているコレクション・クラスを継承したクラスでも実施可能である。
３．  同期マップ・クラスのキー（ｋｅｙ）をスレッド固有の値で利用しているクラス
【００４１】
図２は、本発明の実施態様における、図１に示すメモリ内にある第１のＪａｖａコード（１０８）を第２のＪａｖａコード（１１０）に変換する処理フローの概要を示す。
コンピュータ・システム（図１、１００）は、変換処理の開始に先立って、プログラミング言語Ｊａｖａによるプログラムである第１のＪａｖａコード（１０８）を記憶部（図１、１０３）からメモリ（図１、１０２）内に読み込む。以下の説明では、上記第１のＪａｖａコード（１０８）には、１つのクラス（以下、ＣＬ）が含まれているとするが、上記第１のＪａｖａコード（１０８）には、複数のクラスが含まれていてもよい。第１のＪａｖａコード（１０８）に複数のクラスが含まれる場合、コンピュータ・システム（１００）は、以下のステップ２００〜２０７の処理を、全てのクラスについて実行する。
ステップ２００は、変換処理の開始である。
ステップ２０１では、コンピュータ・システム（１００）は、入力された第１のＪａｖａコード（１０８）に含まれるクラス（ＣＬ）が同期ハッシュ表クラスを継承しているかどうかの判定を行う。該判定では、コンピュータ・システム（１００）が、例えば、ＣＬにおけるクラスの宣言部分に「extends hashtable」が含まれるかどうかをチェックする。「extends hashtable」が含まれる場合、コンピュータ・システム（１００）は、ＣＬが同期ハッシュ表クラスを継承していると判定し、該処理はステップ２０２に進む。一方、「extends hashtable」が含まれない場合、コンピュータ・システム（１００）は、ＣＬが同期ハッシュ表クラスを継承していないと判定し、該処理はステップ２０３に進む。
ステップ２０２では、コンピュータ・システム（１００）は、ＣＬを同期ハッシュ表クラスに対応する並行ハッシュ表クラスを使用するクラスに変換する。すなわち、コンピュータ・システム（１００）は、同期ハッシュ表クラスに対応する並行ハッシュ表クラスのインスタンスを新規に作成するコードを、ＣＬに追加する。次に、コンピュータ・システム（１００）は、ＣＬのスーパークラス（super class）である同期ハッシュ表クラスに属するメソッドを呼び出すコードを、新規に作成された並行ハッシュ表クラスのインスタンスに属するメソッドを呼び出すコードに置き換える。次に、コンピュータ・システム（１００）は、所定のコード変換を行う。該コード変換では、コンピュータ・システム（１００）は、上記置き換えられたコードが、所定の条件を満たすことに応じて、ＣＬに含まれるコードを所定のコードに変換する。該変換では、コンピュータ・システム（１００）は、例えば、ＣＬから不必要な同期のためのコードを除去する。なお、ステップ２０２については、図３Ａ〜図３Ｊの説明において詳しく述べる。次に、該処理はステップ２０３に進む。
ステップ２０３では、コンピュータ・システム（１００）は、ＣＬの中で同期マップ・クラスが宣言されているかどうかの判定を行う。ＣＬの中で同期マップ・クラスが宣言されている場合、該処理はステップ２０４に進む。一方、ＣＬの中で同期マップ・クラスが宣言されていない場合、該処理は終了する。
ステップ２０４では、コンピュータ・システム（１００）は、以下の判定処理を行う。すなわち、コンピュータ・システム（１００）は、ＣＬの中で宣言されている同期マップ・クラスが提供するメソッドにおいて、マップのキーとしてスレッド固有の値が使われているかどうかの判定を行う。ここで、マップのキーとは、コンピュータ・システム（１００）が、マップ・クラスに値（value）を登録する場合に、値（value）との組で指定するキー値である。コンピュータ・システム（１００）は、同一のキー値を指定することで、キー値に対応する登録された値(value)をマップ・クラスから取得することができる。また、スレッド固有の値とは、例えば、スレッド・クラスのメソッド（java.lang.Thread.currentThread()又は、java.lang.Thread.getId()）である。上記スレッド固有の値が使われている場合、該処理はステップ２０５に進む。一方、上記スレッド固有の値が使われていない場合、該処理はステップ２０６に進む。
ステップ２０５では、コンピュータ・システム（１００）は、上記スレッド固有の値をスレッド・ローカルな値に変換する。すなわち、コンピュータ・システム（１００）は、スレッド・ローカル・ストレージ（Thread local storage）を確保するコードを、ＣＬに追加する。コンピュータ・システムは、同期マップ・クラスにアクセスするコードを上記スレッド・ローカル・ストレージにアクセスするのコードに置き換える。次に、コンピュータ・システム（１００）は、所定のコード変換を行う。該コード変換では、コンピュータ・システムは、上記置き換えられたコードが、所定の条件を満たすことに応じて、ＣＬに含まれるコードを所定のコードに変換する。なお、ステップ２０５については、図５Ａ〜図５Ｆの説明において詳しく述べる。次に、該処理はステップ２０６に進む。
ステップ２０６では、コンピュータ・システム（１００）は、同期マップ・クラスを対応する並行マップ・クラスに変換する。次に、コンピュータ・システム（１００）は、所定のコード変換を行う。該コード変換では、コンピュータ・システム（１００）は、上記変換されたクラスに含まれるコードが、所定の条件を満たすことに応じて、上記変換されたクラスに含まれるコードを所定のコードに変換する。該変換では、コンピュータ・システム（１００）は、例えば、実行時のロック衝突を減らす書き換えが可能なコードをＣＬ内から探し、書き換えを実行する。なお、ステップ２０６については、図７Ａ〜図７Ｊの説明において詳しく述べる。コンピュータ・システム（１００）は、上記書き換え後に、該処理を終了する。
ステップ２０７は、変換処理の終了である。
【００４２】
図３Ａは、本発明の実施態様における、図２のステップ２０２の詳細フローを示す。
図２のステップ２０２は、同期ハッシュ表クラスを継承するクラスを同期ハッシュ表クラスに対応する並行ハッシュ表クラスを使用するクラスに変換する処理である。
ステップ３００は、図２のステップ２０２の開始である。
ステップ３０１では、コンピュータ・システム（１００）は、並行ハッシュ表クラスのインスタンスを生成するコードをＣＬに挿入する。
以下の例では、上記生成された並行ハッシュ表クラスのインスタンスが代入されるプライベート（private）変数をccとする。上記挿入されるコードは、例えば、「private concurrentHashtable cc = new concurrentHashtable();」である。上記挿入の終了に応じて、該処理はステップ３０２に進む。
ステップ３０２では、コンピュータ・システム（１００）は、ＣＬにおいて、ＣＬが継承しているスーパークラスの呼び出しを修正する。コンピュータ・システム（１００）は、ＣＬのスーパークラスである同期ハッシュ表クラスに属し、且つ「super.foo()」という形式で記載されているスーパークラスのメソッド呼び出しを、並行ハッシュ表クラスのインスタンスによる呼び出し「cc.foo()」に置き換える。ここで、foo()は、任意のメソッド名を指す。コンピュータ・システム（１００）は、例えば、「super.get(key)」を「cc.get(key)」に置き換える。また、コンピュータ・システム（１００）は、クラスのコンストラクタ内のスーパークラス呼び出しである「super()」をＣＬから削除する。上記置き換え及び削除の終了に応じて、該処理はステップ３０３に進む。
ステップ３０３では、コンピュータ・システム（１００）は、ＣＬにメソッドを追加する。追加されるメソッドは、同期ハッシュ表クラスに属し、且つＣＬでは定義されていないメソッドである。
ユーザは、例えば、ファイルに同期ハッシュ表クラスのＡＰＩを保存しておく。コンピュータ・システム（１００）は、上記ファイルから、同期ハッシュ表クラスのメソッドにアクセスするためのインタフェース及び同期ハッシュ表クラスのメソッドのシグネチャを取得する。コンピュータ・システム（１００）は、ＣＬを精査し、上記インタフェースと同じインタフェースがＣＬに含まれない場合、上記インタフェースを提供するメソッドの定義をＣＬに追加する。コンピュータ・システム（１００）は、追加するメソッドのシグネチャを、追加するメソッドに対応する上記ファイルから取得した同期ハッシュ表クラスのメソッドと同一のシグネチャにする。また、コンピュータ・システム（１００）は、追加するメソッドの実装を「return cc.foo();」とする。ただし、上記追加するメソッドに対応する同期ハッシュ表クラスのメソッドの戻り値がvoidである場合、コンピュータ・システム（１００）は、上記追加するメソッドの実装を「cc.foo();」とする。ここで、foo()は、上記追加するメソッドに対応する同期ハッシュ表クラスのメソッドである。
ステップ３０４では、コンピュータ・システム（１００）は、ＣＬのコードを書き換える。コンピュータ・システム（１００）は、ステップ３０２で置き換えられたメソッド呼び出しを含むコード（以下、第１のコード）をロックの獲得及びロックの解放を原子的に実行するためのコード（以下、第２のコード）に書き換える。該書き換えは、下記図３Ｂ〜図３Ｅを参照して別途説明する。
ステップ３０５では、コンピュータ・システム（１００）は、ＣＬに含まれる同期ブロックを修正する。ステップ３０２においてスーパークラスのメソッド呼び出しに替えて置き換えたメソッド呼び出しが同期ブロックに挟まれている場合、コンピュータ・システム（１００）は、該同期ブロックを修正する。該修正は、下記図３Ｆ〜図３Ｊを参照して別途説明する。
【００４３】
なお、図３Ａの各ステップは、以下の条件を満たせば任意の順序を取ることができる。
・ステップ３０５は、ステップ３０１の後で実行されること。
・ステップ３０２は、ステップ３０１の後で実行されること。
・ステップ３０３は、ステップ３０２の後で実行されること。
・ステップ３０４は、ステップ３０２の後で実行されること。但し、ステップ３０４がステップ３０３より先に実行される場合、ステップ３０４がステップ３０３より後に実行される場合に比べ、コードの書き換えが行われる機会が減る可能性がある。
【００４４】
図３Ｂ〜図３Ｅの各図は、本発明の実施態様における、図３Ａのステップ３０４における処理の詳細フローを示す。
以下の例では、条件式としてｉｆ文を使用しているが、条件式はｉｆ文に限らない。条件式は、言語に用意された条件判定を行うための予約語であればよく、例えばＳｗｉｔｃｈ文であってもよい。
【００４５】
以下に、図３Ｂのステップ３１０〜３１９について説明する。
ステップ３１０は、図３Ａのステップ３０４の始まりを示す。
ステップ３１１では、コンピュータ・システム（１００）は、ＣＬ内にメソッド呼び出しcc.put(k,v)があるかどうかを判定する。ここで、メソッドput(k,v)は、キー値を指定して該キー値に対応する値を並行ハッシュ表クラスのテーブルに格納するメソッドである。kはキー値を格納する任意の変数を表す。また、vは上記キー値に対応する値を格納する任意の変数を表す。なお、判定されるcc.put(k,v)は、次のステップ３１２でまだ取り出されていないcc.put(k,v)である。ＣＬ内にcc.put(k,v)がある場合、該処理はステップ３１２に進む。一方、cc.put(k,v)がない場合、ステップ３１８に進み、終了する。
ステップ３１３では、コンピュータ・システム（１００）は、上記cc.put(k,v)がｉｆ文に支配されているかどうかを判定する。cc.put(k,v)がｉｆ文に支配されているとは、ｉｆ文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。cc.put(k,v)がｉｆ文に支配されている場合、該処理はステップ３１４に進む。一方、cc.put(k,v)がｉｆ文に支配されていない場合、該処理は３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３１４では、コンピュータ・システム（１００）は、上記ｉｆ文の条件節においてcc.get(k)の戻り値がnullと比較されているかどうかを判定する。ここで、メソッドget(k)は、キー値kを指定して該キー値に対応する値を並行ハッシュ表クラスのテーブルから取得するメソッドである。ｉｆ文の条件節においてcc.get(k)の戻り値がnullと比較されているとは、条件節に例えば「cc.get(k)==NULL」が記載されていることをいう。cc.get(k)の戻り値がnullと比較されている場合、該処理はステップ３１５に進む。一方、比較されていない場合、該処理はステップ３１９に進む。
ステップ３１５では、コンピュータ・システム（１００）は、cc.get(k)の戻り値がnullの場合、cc.put(k,v)が実行されるかどうかを判定する。上記戻り値がnullの場合にcc.put(k,v)が実行されるとは、ｉｆ文が、例えば「if(cc.get(k)==NULL){v=cc.put(k,v);}」の場合である。cc.put(k,v)が実行される場合、該処理はステップ３１６に進む。一方、cc.put(k,v)が実行されない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３１６では、コンピュータ・システム（１００）は、cc.get(k)の戻り値がnullと等しくない場合、実行される命令がないかを判定する。上記戻り値がnullと等しくない場合、実行される命令がないとは、if文が、例えば「if(cc.get(k)==NULL){v=cc.put(k,v);}else{//nop}」の場合である。実行される命令がない場合、該処理はステップ３１７に進む。一方、実行される命令がある場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３１７では、コンピュータ・システム（１００）は、cc.get(k)がif文を直接支配するかどうかを判定する。cc.get(k)がif文を直接支配するとは、if文が実行される前に必ずcc.get(k)が実行され、且つcc.get(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。cc.get(k)がif文を直接支配する場合、該処理はステップ３２１に進む。一方、cc.get(k)がif文を直接支配しない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３１９では、コンピュータ・システム（１００）は、ｉｆ文の条件節においてcc.containsKey(k)の戻り値を評価しているかどうかを判定する。cc.containsKey(k)の戻り値を評価するとは、条件節に例えば「cc.containsKey(k)==FALSE」が記載されていることをいう。ここで、メソッドcontainsKey(k)は、キー値kを指定して該キー値に対応する値が並行ハッシュ表クラスに含まれるかどうかを返すメソッドである。cc.containsKey(k)の戻り値が評価されている場合、該処理はステップ３３１に進む。一方、比較されていない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
【００４６】
以下に、図３Ｃのステップ３２１〜３２５について説明する。
ステップ３２１では、コンピュータ・システム（１００）は、ｉｆ文がcc.put(k,v)を直接支配するかどうかを判定する。ｉｆ文がcc.put(k,v)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。ｉｆ文がcc.put(k,v)を直接支配する場合、該処理はステップ３２２に進む。一方、直接支配しない場合、該処理はステップ３２５に進む。
ステップ３２２では、コンピュータ・システム（１００）は、上記cc.get(k)の戻り値がnullと等しい場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ３２５に進む。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ３２３に進む。
ステップ３２３では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ３２４に進む。一方、メソッドが取得されなかった場合、該処理はステップ３２５に進む。
ステップ３２４では、コンピュータ・システム（１００）は、cc.get(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。上記putIfAbsent()メソッドについては、ＵＲＬ（http://Java.sun.com/Javase/6/docs/api/Java/util/concurrent/ConcurrentMap.html#putIfAbsent(K,%20V)）を参照されたい。
ステップ３２５では、コンピュータ・システム（１００）は、cc.get(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでを「if(cc.get(k)== null){synchronized(cc){」と「}}」とで囲む。上記囲むことが終了したら、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
【００４７】
以下に、図３Ｄのステップ３３１〜３３７について説明する。
ステップ３３１では、コンピュータ・システム（１００）は、cc.containsKey(k)の戻り値がfalseの場合、cc.put(k,v)が実行されるかどうかを判定する。上記戻り値がfalseの場合にcc.put(k,v)が実行されるとは、ｉｆ文が、例えば「if(cc.containsKey(k)==false){v=cc.put(k,v);}」の場合である。cc.put(k,v)が実行される場合、該処理はステップ３３２に進む。一方、cc.put(k,v)が実行されない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３３２では、コンピュータ・システム（１００）は、cc.put(k,v)の戻り値が使用されているかどうかを判定する。cc.put(k,v)の戻り値がＣＬ内で使用されている場合、該処理はステップ３３３に進む。一方、使用されていない場合、該処理はステップ３３６に進む。
ステップ３３３では、コンピュータ・システム（１００）は、cc.containsKey(k)の戻り値がtrueの場合、戻り値が使用されるcc.get(k)があるかどうかを判定する。戻り値が使用されるcc.get(k)があるとは、if文が、例えば「if(cc.containsKey(k)==true){v=cc.get(k);}」の場合、vを使用するコードがＣＬに含まれていることをいう。戻り値が使用されるcc.get(k)が含まれる場合、該処理はステップ３３４に進む。一方、含まれない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３３４では、コンピュータ・システム（１００）は、cc.get()及びcc.put()から２つを後支配する位置までに実行される文はあるかどうかを判定する。cc.get()及びcc.put()から２つを後支配する位置とは、cc.get()が実行された後に必ず実行される命令と、cc.put()が実行された後に必ず実行される命令とのうち、最初に共通で実行される命令のコードの位置である。実行される文がない場合、該処理はステップ３３５に進む。一方、実行される文がある場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３３５では、コンピュータ・システム（１００）は、cc.containsKey (k)がif文を直接支配するかどうかを判定する。cc.containsKey(k)がif文を直接支配するとは、if文が実行される前に必ずcc.containsKey(k)が実行され、且つcc.containsKey(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。cc.containsKey(k)がif文を直接支配する場合、該処理はステップ３４１に進む。一方、cc.containsKey(k)がif文を直接支配しない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３３６では、コンピュータ・システム（１００）は、cc. containsKey(k)の戻り値がtrueの場合、実行される文がないかどうかを判定する。上記戻り値がtrueの場合において、実行される文がないとは、if文が、例えば「if(cc.containsKey(k)==true){//nop}」の場合である。実行される文がない場合、該処理はステップ３３７に進む。一方、実行される文がある場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３３７では、コンピュータ・システム（１００）は、cc.containsKey(k)がif文を直接支配するかどうかを判定する。cc.containsKey(k)がif文を直接支配する場合、該処理はステップ３４６に進む。一方、cc.containsKey(k)がif文を直接支配しない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
【００４８】
以下に、図３Ｅのステップ３４１〜３５０について説明する。
ステップ３４１では、コンピュータ・システム（１００）は、ｉｆ文がcc.put(k,v)及びcc.get(k)を直接支配するかどうかを判定する。ｉｆ文がcc.put(k,v) 及びcc.get(k)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にcc.put(k,v)及びcc.get(k)が含まれていることをいう。ｉｆ文がcc.put(k,v)及びcc.get(k)を直接支配する場合、該処理はステップ３４２に進む。一方、ｉｆ文がcc.put(k,v)及びcc.get(k)を直接支配しない場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３４２では、コンピュータ・システム（１００）は、上記cc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ３４３に進む。
ステップ３４３では、コンピュータ・システム（１００）は、上記cc.containskey(k)の戻り値がtrueの場合に実行されるコード部分において、cc.get(k)の後にも実行文があるかどうかを判定する。cc.get(k)の後にも実行文がある場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。一方、cc.get(k)の後に実行文がない場合、該処理はステップ３４４に進む。
ステップ３４４では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ３４５に進む。一方、メソッドが取得されなかった場合、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３４５では、コンピュータ・システム（１００）は、cc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３４６では、コンピュータ・システム（１００）は、ｉｆ文がcc.put(k,v)を直接支配するかどうかを判定する。ｉｆ文がcc.put(k,v)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にcc.put(k,v)が含まれていることをいう。ｉｆ文がcc.put(k,v)を直接支配する場合、該処理はステップ３４７に進む。一方、ｉｆ文がcc.put(k,v)を直接支配しない場合、該処理はステップ３５０に進む。
ステップ３４７では、コンピュータ・システム（１００）は、上記cc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、cc.put(k,v)の後にも実行文があるかどうかを判定する。cc.put(k,v)の後にも実行文がある場合、該処理はステップ３５０に進む。一方、cc.put(k,v)の後に実行文がない場合、該処理はステップ３４８に進む。
ステップ３４８では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ３４９に進む。一方、メソッドが取得されなかった場合、該処理はステップ３５０に進む。
ステップ３４９では、コンピュータ・システム（１００）は、cc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=cc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
ステップ３５０では、コンピュータ・システム（１００）は、cc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをif ((v = cc.get(key)) == null) { synchronized(cc) { if ((v =cc.get(key)) == null) { v = cc.put(key, value); } } }で置き換える。上記置き換えることが終了したら、該処理はステップ３１１に戻り、別のcc.put(k,v)についての処理を開始する。
【００４９】
図３Ｆ〜図３Ｊの各図は、本発明の実施態様における、図３Ａのステップ３０５における処理の詳細フローを示す。
なお、以下の図３Ｆ〜図３Ｊの説明において、ＳＢ１、ＳＢ２及びＳＢ３はそれぞれ異なる同期ブロックを示す。
ステップ３０５では、コンピュータ・システム（１００）は、同期ブロック（以下、ＳＢ１）の修正を行う。コンピュータ・システム（１００）は、ＳＢ１に対して以下の各処理（図３Ｆ〜図３Ｊ）を行う。
【００５０】
図３Ｆは、本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下でＳＢ１を除去する処理のフローを示す。
ステップ３５１は、図３Ａのステップ３０５の始まりを示す。
ステップ３５２では、コンピュータ・システム（１００）は、ＳＢ１内に並行ハッシュ表クラスのインスタンスccに属するメソッド呼び出しが１つ以下あるかどうかを判定する。１つ以下あるとは、１つ含まれるか又は含まれないことである。ここで、コンピュータ・システム（１００）は、上記ステップ３０４で書き換えられた結果に含まれているインスタンスccに属するメソッド呼び出しのコードについては、それぞれを１つと数えず、上記書き換えられた結果に含まれているインスタンスccに属するメソッド呼び出しのコード全体を１つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が１つ以下の場合、該処理はステップ３５３に進む。一方、上記数えられたメソッド呼び出しのコード数が２つ以上の場合、該処理はステップ３６１に進む。
ステップ３５３では、コンピュータ・システム（１００）は、ＳＢ１内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、インスタンス変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ３６１に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ３５４に進む。
ステップ３５４では、コンピュータ・システム（１００）は、ＳＢ１内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、スタティック変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ３６１へ進む。一方、上記スタティック変数にアクセスするコードが含まれていない場合、該処理はステップ３５５に進む。
ステップ３５５では、コンピュータ・システム（１００）は、ＳＢ１を除去する。上記除去は、コンピュータ・システム（１００）が、コードからＳＢ１についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ３５６へ進み、ステップ３０５は終了する。
上記ステップ３５１〜３５５の処理によって、ロック衝突の機会が減少する。
【００５１】
図３Ｇは、本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ３６１では、コンピュータ・システム（１００）は、ＳＢ１内にv = cc.get()が１つだけ存在するかどうかを判定する。コンピュータ・システム（１００）は、ＳＢ１で囲まれているインスタンスccからのgetメソッド呼び出し（v =cc.get()）のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が１つの場合、該処理はステップ３６２に進む。一方、上記getメソッドの数が０又は２以上の場合、該処理はステップ３７１に進む。
ステップ３６２では、コンピュータ・システム（１００）は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム（１００）は、上記戻り値vについてのnullチェックをするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ３６３に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ３７１に進む。
ステップ３６３では、コンピュータ・システム（１００）は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計２回以上あるかどうかを判定する。コンピュータ・システム（１００）は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計２回以上ある場合、該処理はステップ３６４に進む。一方、上記アクセスするコードが０または１回ある場合、該処理はステップ３７１に進む。
ステップ３６４では、コンピュータ・システム（１００）は、ＳＢ１の外側にif((v=cc.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ３６５に進む。ステップ３６５は、ステップ３０５の終了を示す。
上記ステップ３６１〜３６５の処理によって、ロック衝突時間が短縮される。
【００５２】
図３Ｈ、図３Ｉ及び図３Ｊの各図は、本発明の実施態様における、図３Ａのステップ３０５における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロック（read lock）に置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロック（write lock）に更に置き換える処理フローを示す。
【００５３】
ここで、「リード・ロック」とは、書き込み動作がない限り複数のスレッドに同時に読み出し動作を許可することができるロックをいう。また、「ライト・ロック」とは、スレッドが書き込み動作を行う際に他のスレッドを排他制御するために使用するロックをいう。同期ブロックをリード・ロック又はライト・ロックに置き換えることにより、読み出し動作に不必要な排他的ロックを減らし、ロック衝突の機会が減少する。
【００５４】
以下に、図３Ｈのステップ３７１〜３７６について説明する。
ステップ３７１では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理は、ステップ３７６に進み終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ３７２に進む。
ステップ３７２では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理はステップ３７６に進み、終了する。一方、上記書き込みコードが含まれていない場合、該処理は、ステップ３７３に進む。
ステップ３７３では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているインスタンスccに属する参照に関するメソッド呼び出しのコードの数（Ｍ）を数える。インスタンスccに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ３７４では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値（Ｎ）を求める。
ステップ３７５では、コンピュータ・システム（１００）は、Ｍ＋Ｎ＞＝２が成り立つかどうかを判定する。コンピュータ・システム（１００）は、Ｍ＋Ｎを計算する。Ｍ＋Ｎが２以上の場合、該処理はステップ３８１に進む。一方、Ｍ＋Ｎが１以下の場合、該処理はステップ３７６に進み、終了する。
【００５５】
以下に、図３Ｉのステップ３８１〜３８６について説明する。
ステップ３８１では、コンピュータ・システム（１００）は、ＳＢ１にアクセスがあるｃｃについての更新に関する呼び出しが、ＣＬ内にも存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査によって、ＳＢ１に囲まれた範囲に含まれているインスタンスccに属する更新に関するメソッド呼び出しに対応する、インスタンスccに属する更新に関するメソッド呼び出しのコードがＣＬ内に発見された場合、該処理はステップ３８２に進む。一方、発見されなかった場合、該処理はステップ３８５に進む。ここで、ccに属する更新に関するメソッド呼び出しとは、例えば、cc.put()である。
ステップ３８２では、コンピュータ・システム（１００）は、発見された更新に関する呼び出しが第２の同期ブロック（以下、ＳＢ２）で囲まれているかどうかを判定する。コンピュータ・システム（１００）は、上記発見されたコードが、ＳＢ２で囲まれた範囲に含まれているかどうかを調べる。含まれている場合、該処理はステップ３８３に進む。一方、含まれていない場合、該処理はステップ３８５に進む。
ステップ３８３では、コンピュータ・システム（１００）は、ＳＢ２内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ２に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ３８５に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ３８４に進む。
ステップ３８４では、コンピュータ・システム（１００）は、ＳＢ１のロックをリード・ロックに置き換える。また、コンピュータ・システム（１００）は、ＳＢ２のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ３８５に進む。
ステップ３８５では、コンピュータ・システム（１００）は、ステップ３７４で求めた合計値（Ｎ）を判定する。Ｎ＞０の場合、該処理はステップ３８７に進む。一方、Ｎ＞０以外の場合、該処理はステップ３８６に進み、終了する。
ステップ３８７では、コンピュータ・システム（１００）は、ＳＢ１内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがＣＬ内に存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査により、ＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数への書き込み、ＣＬ内に発見された場合、該処理はステップ３８８に進む。一方、発見されなかった場合、該処理はステップ３９２に進み、終了する。
ステップ３８８では、コンピュータ・システム（１００）は、発見された更新が第３の同期ブロック（以下、ＳＢ３）で囲まれているかどうかを判定する。上記発見されたコードがＳＢ３に含まれている場合、該処理はステップ３８９に進む。一方、含まれていない場合、該処理はステップ３９２に進み、終了する。
ステップ３８９では、コンピュータ・システム（１００）は、ＳＢ３内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ３に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ３９２に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ３９０に進む。
ステップ３９０では、コンピュータ・システム（１００）は、ＳＢ１のロックがリード・ロックに置き換わっていないならば、ＳＢ１の該ロックをリード・ロックに置き換える。
ステップ３９１では、コンピュータ・システム（１００）は、ＳＢ３のロックをライト・ロックに置き換える。
ステップ３９２及びステップ３９３はいずれも、ステップ３０５の終了を示す。
【００５６】
図４Ａは、本発明の実施態様における、図３Ａのステップ３０４におけるコード変換の例を示す。
図４Ａは、第１のコードと第２のコードとの対応を示す。コード（４０１）及びコード（４０２）は、第１のコードの例である。コード（４０３）及びコード（４０４）は、第２のコードの例である。
コンピュータ・システム（１００）は、コード（４０１）及びコード（４０２）それぞれについて、図３Ａのステップ３０４（詳細には、図３Ｂ〜図３Ｅの各ステップ）の処理を行う。該処理により、コード（４０１）及びコード（４０２）は、コード（４０３）又はコード（４０４）に書き換えられる。ここで、ccがメソッド（get()/put()）の組を原子的に実行するputIfAbsent()メソッドを持っている並行ハッシュ表クラスのインスタンスである場合、コード（４０１）及びコード（４０２）は、コード（４０３）に変換される。putIfAbsent()メソッドを持っていない並行ハッシュ表クラスのインスタンスである場合、コード（４０１）及びコード（４０２）は、コード（４０４）に変換される。
【００５７】
図４Ｂは、本発明の実施態様における、図１に示すメモリ（１０２）内にある第１のＪａｖａコード（１０８）であるＣＬ（クラスＸ）を示す。
図４Ｃは、本発明の実施態様における、図１に示すメモリ（１０２）内にある第２のＪａｖａコード（１１０）であるＣＬ（クラスＸ）を示す。
以下に、図４Ｂに示す変換前の第１のＪａｖａコードであるＣＬ（クラスＸ）を、図３Ａに示す変換処理を適用して、図４Ｃに示す変換後の第２のＪａｖａコードであるＣＬ（クラスＸ）に変換する例を示す。
【００５８】
図４Ｂでは、クラスＸに継承予約語extendsがある。クラスＸの一行目「public class X extendsHashtable」は、クラスＸが、ハッシュ表クラスを継承することの宣言である。よって、クラスＸは、図２のステップ２０１（ハッシュ表クラスの継承）の条件を満たす。従って、クラスＸは、図３Ａの各ステップで変換処理される。
コンピュータ・システム（１００）は、図３Ａのステップ３０１（インスタンスを生成するコードの挿入）に従い、ハッシュ表クラスに対応する並行ハッシュ表クラスのインスタンスを生成するコードをクラスＸに挿入する。挿入されたコードは、「private concurrentHashtable cc = new concurrentHashtable();」である（図４Ｃの//X’00を見よ）。 
コンピュータ・システム（１００）は、図３Ａのステップ３０２（スーパークラスの呼び出しの修正）に従い、スーパークラスの呼び出しを修正する。この修正により、コンストラクタ内のスーパークラスの呼び出し（図４Ｂの//X02を見よ）は、削除されるか、又はコメント化されたスーパークラスの呼び出し（図４Ｃの//X’02を見よ）に修正される。また、スーパークラスの呼び出し（図４Ｂの//X05，//X09，//X22を見よ）は、並行ハッシュ表クラスのインスタンスccの呼び出し（図４Ｃの//X’05，//X’07，//X’19，//X’22を見よ）に修正される。
コンピュータ・システム（１００）は、ステップ３０３（同期ハッシュ表クラスに属するメソッドの追加）に従い、メソッドを追加する。なお、クラスＸには、ステップ３０３によって追加されるメソッドはない。
コンピュータ・システム（１００）は、ステップ３０４（コードの書き換え）に従い、コードを書き換える。なお、本クラスＸには、ステップ３０４によって書き換えられるコードはない。
コンピュータ・システム（１００）は、ステップ３０５（同期ブロックの修正）に従い、コードを書き換える。//X04〜//X10では、ccに関するアクセスは//X05のcc.get()だけである。また、//X06のif (ret == null) { … }のパスにおいて、parentが２回以上参照されている。よって、//X04の同期修飾子（synchronized）が除去される。また、//X06のif (ret == null) { … }のパスが同期ブロックで囲まれ、「ret=cc.get();if(ret == null) 」が同期ブロックの外側に複製される。
よって、変換後の第２のＪａｖａコードは、図４Ｃに示すコードになる。
【００５９】
図５Ａは、本発明の実施態様における、図２のステップ２０５の詳細フローを示す。
図２のステップ２０５は、同期マップ・クラスが提供するメソッドにおいて、マップのキーとしてスレッド固有の値が使われている場合の変換処理である。
ステップ５００は、図２のステップ２０５の開始である。
ステップ５０１では、コンピュータ・システム（１００）は、同期マップ・クラスのインスタンス生成コードが使用されている場合、スレッド・ローカル・クラス（java.lang.ThreadLocal）のインスタンスを生成するコードに置き換える。新たに挿入されるコードは、例えば、「ThreadLocal tlh = new ThreadLocal();」である。
ここで、「スレッド・ローカル・クラス」とは、スレッド・ローカル変数、すなわち１つの論理変数でありながら、別々のスレッドで独立した値をもつことを可能にする変数を提供するクラスである。
なお、本明細書では、生成されたスレッド・ローカル・クラスのインスタンスが代入されるprivate変数をtlh、同期マップ・クラスのインスタンス変数をsc、スレッド固有の値をthrとする。
ステップ５０２では、同期マップ・クラスのインスタンスからのメソッド呼び出しを、上記スレッド・ローカルなインスタンスからのメソッド呼び出しに置き換える。具体的には、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()に置き換える。さらに、コンピュータ・システム（１００）は、不要コード除去（dead code elimination）を適用しうる。該適用によって、不要な代入文が削除される。
ステップ５０３において、ステップ５０１及び５０２で置き換えたメソッドが同期ブロックで囲まれている場合、下記の処理を行う。
(ａ)同期ブロックの中に他のインスタンス変数とスタティック変数とが存在しない場合、同期ブロックを除去する。
(ｂ)同期ブロックの中で、インスタンスtlhによるメソッド呼び出しtlh.get()が１つだけ存在する（ア）。上記tlh.get()の戻り値がnullの場合に実行されるパスに、インスタンス変数とスタティック変数の読み書きが２回以上ある（イ）。上記（ア、イ）を満たす場合、もとの同期ブロックを除去する。また、tlh.get()の戻り値がnullの場合に実行されるパスを同期ブロックで囲む。該同期ブロックの内側に「v = tlh.get(); if (v== null)」を複製する。
(ｃ)同期ブロックの中で、インスタンスtlhによるメソッド呼び出しtlh に属する参照メソッド呼び出し（ステップ５０２の書き換え結果は１つと数える)とプライベートなインスタンス変数とスタティック変数との読み出しの数があわせて２つ以上である場合、同期ブロックをリード・ロック（read lock）に置き換える。
さらに、クラス全体で上記のペアに関する変更（プライベートなインスタンス変数とスタティック変数の書き込み）が存在する同期ブロックの内側でライト・ロック（write lock）を挿入する。
なお、図５Ａのステップ５０２及びステップ５０３は、どちらのステップが先に実行されてもよい。
【００６０】
図５Ｂ〜図５Ｆの各図は、本発明の実施態様における、図５Ａのステップ５０３における処理の詳細フローを示す。
ステップ５０３では、コンピュータ・システム（１００）は、同期ブロック（ＳＢ１）の修正を行う。コンピュータ・システム（１００）は、ＳＢ１に対して以下の各処理（図５Ｂ〜図５Ｆ）を行う。
なお、以下の図５Ｂ〜図５Ｆの説明において、ＳＢ１、ＳＢ２及びＳＢ３はそれぞれ異なる同期ブロックを示す。
【００６１】
図５Ｂは、本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下でＳＢ１を除去する処理フローを示す。
ステップ５５１は、図５Ａのステップ５０３の始まりを示す。
ステップ５５２では、コンピュータ・システム（１００）は、ＳＢ１内にインスタンスtlhに属するメソッド呼び出しが１つ以下あるかどうかを判定する。１つ以下あるとは、１つ含まれるか又は含まれないことである。ここで、コンピュータ・システム（１００）は、上記ステップ５０２で書き換えられた結果に含まれているインスタンスtlhに属するメソッド呼び出しのコードについては、それぞれを１つと数えず、上記書き換えられた結果に含まれているインスタンスtlhに属するメソッド呼び出しのコード全体を１つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が１つ以下の場合、該処理はステップ５５３に進む。一方、上記数えられたメソッド呼び出しのコード数が２つ以上の場合、該処理はステップ５６１に進む。
ステップ５５３では、コンピュータ・システム（１００）は、ＳＢ１内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、インスタンス変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ５６１に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ５５４に進む。
ステップ５５４では、コンピュータ・システム（１００）は、ＳＢ１内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、スタティック変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理は、ステップ５６１へ進む。一方、上記スタティック変数にアクセスするコードが含まれていない場合、該処理はステップ５５５に進む。
ステップ５５５では、コンピュータ・システム（１００）は、ＳＢ１を除去する。上記除去は、コンピュータ・システム（１００）が、コードからＳＢ１についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ５５６へ進み、ステップ５０３は終了する。
上記ステップ５５１〜５５５の処理によって、ロック衝突の機会が減少する。
【００６２】
図５Ｃは、本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ５６１では、コンピュータ・システム（１００）は、ＳＢ１内にv = tlh.get()が１つだけ存在するかどうかを判定する。コンピュータ・システム（１００）は、ＳＢ１で囲まれているインスタンスtlhからのgetメソッド呼び出し（v= tlh.get()）のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が１つの場合、該処理はステップ５６２に進む。一方、上記getメソッドの数が０又は２以上の場合、該処理はステップ５７１に進む。
ステップ５６２では、コンピュータ・システム（１００）は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム（１００）は、上記戻り値vについてのnullチェックをするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ５６３に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ５７１に進む。
ステップ５６３では、コンピュータ・システム（１００）は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計２回以上あるかどうかを判定する。コンピュータ・システム（１００）は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計２回以上ある場合、該処理はステップ５６４に進む。一方、上記アクセスするコードが０又は１回ある場合、該処理はステップ５７１に進む。
ステップ５６４では、コンピュータ・システム（１００）は、ＳＢ１の外側にif((v= tlh.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ５６５に進む。ステップ５６５は、ステップ５０３の終了を示す。
上記ステップ５６１〜５６５の処理によって、ロック衝突時間が短縮される。
【００６３】
図５Ｄ、図５Ｅ及び図５Ｆの各図は、本発明の実施態様における、図５Ａのステップ５０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロック（read lock）に置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロック（write lock）に更に置き換える処理フローを示す。
【００６４】
以下に、図５Ｄのステップ５７１〜５７６について説明する。
ステップ５７１では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ５７６に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理は、ステップ５７２に進む。
ステップ５７２では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理はステップ５７６に進み、終了する。一方、上記書き込みコードが含まれていない場合、該処理はステップ５７３に進む。
ステップ５７３では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているインスタンスscに属する参照に関するメソッド呼び出しのコードの数（Ｍ）を数える。インスタンスscに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ５７４では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値（Ｎ）を求める。
ステップ５７５では、コンピュータ・システム（１００）は、Ｍ＋Ｎ＞＝２が成り立つかどうかを判定する。コンピュータ・システム（１００）は、Ｍ＋Ｎを計算する。Ｍ＋Ｎが２以上の場合、該処理はステップ５８１に進む。一方、Ｍ＋Ｎが１以下の場合、該処理はステップ５７６に進み、終了する。
【００６５】
以下に、図５Ｅのステップ５８１〜５８６について説明する。
ステップ５８１では、コンピュータ・システム（１００）は、ＳＢ１にアクセスがあるtlhについての更新に関する呼び出しが、ＣＬ内にも存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査によって、ＳＢ１に囲まれた範囲に含まれているインスタンスtlhに属する更新に関するメソッド呼び出しに対応する、インスタンスtlhに属する更新に関するメソッド呼び出しのコードがＣＬ内に発見された場合、該処理はステップ５８２に進む。一方、発見されなかった場合、該処理はステップ５８５に進む。ここで、tlhに属する更新に関するメソッド呼び出しとは、例えば、tlh.put()である。
ステップ５８２では、コンピュータ・システム（１００）は、発見された更新に関する呼び出しが第２の同期ブロック（以下、ＳＢ２）で囲まれているかどうかを判定する。コンピュータ・システム（１００）は、上記発見されたコードが、ＳＢ２で囲まれた範囲に含まれているかを調べる。含まれている場合、該処理はステップ５８３に進む。一方、含まれていない場合、該処理はステップ５８５に進む。
ステップ５８３では、コンピュータ・システム（１００）は、ＳＢ２内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ２に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ５８５に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ５８４に進む。
ステップ５８４では、コンピュータ・システム（１００）は、ＳＢ１のロックをリード・ロックに置き換える。また、コンピュータ・システム（１００）は、ＳＢ２のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ５８５へ進む。
ステップ５８５では、コンピュータ・システム（１００）は、ステップ５７４で求めた合計値（Ｎ）を判定する。Ｎ＞０の場合、ステップ５８７に進む。一方、Ｎ＞０以外の場合、該処理はステップ５８６に進み、終了する。
【００６６】
以下に、図５Ｆのステップ５８７〜５９３について説明する。
ステップ５８７では、コンピュータ・システム（１００）は、ＳＢ１内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがＣＬ内に存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査により、ＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数を更新するコードが、ＣＬ内に発見された場合、該処理はステップ５８８に進む。一方、発見されなかった場合、該処理はステップ５９２に進み、終了する。
ステップ５８８では、コンピュータ・システム（１００）は、発見された更新が第３の同期ブロック（以下、ＳＢ３）で囲まれているかどうかを判定する。コンピュータ・システム（１００）は、上記発見されたコードが、ＳＢ３で囲まれた範囲に含まれているかを調べる。上記発見されたコードがＳＢ３に含まれている場合、該処理はステップ５８９に進む。一方、含まれていない場合、該処理はステップ５９２に進み、終了する。
ステップ５８９では、コンピュータ・システム（１００）は、ＳＢ３内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ３に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ５９２に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ５９０に進む。
ステップ５９０では、コンピュータ・システム（１００）は、ＳＢ１のロックがリード・ロックに置き換わっていないならば、ＳＢ１の該ロックをリード・ロックに置き換える。
ステップ５９１では、コンピュータ・システム（１００）は、ＳＢ３のロックをライト・ロックに置き換える。
ステップ５９２及び５９３のいずれも、ステップ５０３の終了を示す。
【００６７】
図６Ａは、図１に示すメモリ（１０２）内にある第１のＪａｖａコード（１０８）であるＣＬ（クラスＹ）を示す。
図６Ｂは、図１に示すメモリ（１０２）内にある第２のＪａｖａコード（１１０）であるＣＬ（クラスＹ）を示す。
以下に、図６Ａに示す変換前の第１のＪａｖａコードであるＣＬ（クラスＹ）を、図５Ａに示す変換処理を適用して、図６Ｂに示変換後の第２のＪａｖａコードであるＣＬ（クラスＹ）に変換する例を示す。
【００６８】
図６Ａでは、クラスＹに継承予約語extendsがない。
クラスＹは、ハッシュ表クラスを継承しておらず、図２のステップ２０１の条件を満たさない。また、クラスＹは、同期マップ・クラスが宣言されており（図６ＡのY00）、且つスレッド固有の値threadがキーとして使用されているので（例えば、図６ＡのY06）、図２のステップ２０３及び２０４の条件を満たす。よって、クラスＹは、図５Ａの各ステップで変換処理される。
【００６９】
図５Ａのステップ５０１において、図６Ａの２行目に示すように「ThreadLocal tlh = new ThreadLocal();」が宣言される（図６Ｂの//Y’00）。同時に、図６Ａの２行目のハッシュマップによるインスタンスscの生成（コレクション・クラスの同期マップラッパーがかかっている）のコード（図６Ａの//Y00）)は除去されている。
次に、図５Ａのステップ５０２によって、固有のスレッドthreadを引数に有する図６Ａの//Y05、//Y10、//Y13 が書き換えられる。その結果、図６Ｂの//Y’05、//Y’10、//Y’13のように書き換えられる。その後、さらに、//Y04、//Y09が削除される。
図６Ａでは、同期ブロックに囲まれた部分はないので、ステップ５０３によって書き換えられるコードはない。よって、変換後の第２のＪａｖａコードは、図６Ｂに示すコードになる。
【００７０】
図７Ａは、本発明の実施態様における、図２のステップ２０６の詳細フローである。図２のステップ２０６は、同期マップ・クラスを対応する並行マップ・クラスに変換する処理である。
ステップ７００は、図２のステップ２０６の開始である。
ステップ７０１では、コンピュータ・システム（１００）は、同期マップ・クラスのインスタンスscを生成しているコードを、同期マップ・クラスに対応する並行マップ・クラスのインスタンスを生成するコードに置き換える。本明細書では、並行マップ・クラスをconcurrentMapというクラスとする。また、本明細書では、生成された上記並行マップ・クラスのインスタンスが代入されるプライベート変数もscとする。さらに、コンピュータ・システム（１００）は、上記scに関する型宣言を必要に応じて置き換える。
ステップ７０２では、コンピュータ・システム（１００）は、ＣＬのコードを書き換える。コンピュータ・システム（１００）は、ステップ７０１で置き換えられたメソッド呼び出しを含むコード（以下、第１のコード）をロックの獲得及びロックの解放を原子的に実行するためのコード（以下、第２のコード）に書き換える。該書き換えは、下記図７Ｂ〜図７Ｅを参照して別途説明する。
ステップ７０３では、コンピュータ・システム（１００）は、ステップ７０１及び７０２で置き換えたメソッドが同期ブロックで囲まれている場合、同期ブロックを修正する。該修正は、下記図７Ｆ〜図７Ｊを参照して別途説明する。
なお、図７Ａのステップ７０２及びステップ７０３は、どちらのステップが先に実行されてもよい。
【００７１】
図７Ｂ〜図７Ｅの各図は、本発明の実施態様における、図７Ａのステップ７０２における処理の詳細フローを示す。
以下の例では、条件式としてｉｆ文を使用しているが、条件式はｉｆ文に限らない。条件式は、言語に用意された判定を行うための予約語であればよく、例えばＳｗｉｔｃｈ文であってもよい。
【００７２】
以下に、図７Ｂのステップ７１０〜７１９について説明する。
ステップ７１０は、図７Ａのステップ７０２の始まりを示す。
ステップ７１１では、コンピュータ・システム（１００）は、ＣＬ内にメソッド呼び出しsc.put(k,v)があるかどうかを判定する。ここで、メソッドput(k,v)は、キー値を指定して該キー値に対応する値を並行マップ・クラスのテーブルに格納するメソッドである。ｋはキー値を格納する任意の変数を表す。また、vは上記キー値に対応する値を格納する任意の変数を表す。なお、判定されるsc.put(k,v)は、次のステップ７１２でまだ取り出されていないsc.put(k,v)である。ＣＬ内にsc.put(k,v)がある場合、該処理はステップ７１２に進む。一方、sc.put(k,v)がない場合、ステップ７１８に進み、終了する。
ステップ７１３では、コンピュータ・システム（１００）は、上記sc.put(k,v)がｉｆ文に支配されているかどうかを判定する。sc.put(k,v)がｉｆ文に支配されているとは、ｉｆ文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。sc.put(k,v)がｉｆ文に支配されている場合、該処理はステップ７１４に進む。一方、支配されていない場合、該処理は７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７１４では、コンピュータ・システム（１００）は、上記ｉｆ文の条件節においてsc.get(k)の戻り値がnullと比較されているかどうかを判定する。ここで、メソッドget(k)は、キー値kを指定して該キー値に対応する値を並行マップ・クラスのテーブルから取得するメソッドである。ｉｆ文の条件節においてsc.get(k)の戻り値がnullと比較されているとは、条件節に例えば「sc.get(k)==NULL」が記載されていることをいう。sc.get(k)の戻り値がnullと比較されている場合、該処理はステップ７１５に進む。一方、比較されていない場合、該処理はステップ７１９に進む。
ステップ７１５では、コンピュータ・システム（１００）は、sc.get(k)の戻り値がnullの場合、sc.put(k,v)が実行されるかどうかを判定する。上記戻り値がnullの場合にsc.put(k,v)が実行されるとは、ｉｆ文が、例えば「if(sc.get(k)==NULL){v=sc.put(k,v);}」の場合である。sc.put(k,v)が実行される場合、該処理はステップ７１６に進む。一方、sc.put(k,v)が実行されない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７１６では、コンピュータ・システム（１００）は、sc.get(k)の戻り値がnullと等しくない場合、実行される命令がないかどうかを判定する。上記戻り値がnullと等しくない場合、実行される命令がないとは、if文が、例えば「if(sc.get(k)==NULL){v=sc.put(k,v);}else{//nop}」の場合である。実行される命令がない場合、該処理はステップ７１７に進む。一方、実行される命令がある場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７１７では、コンピュータ・システム（１００）は、sc.get(k)がif文を直接支配するかどうかを判定する。sc.get(k)がif文を直接支配するとは、if文が実行される前に必ずsc.get(k)が実行され、且つsc.get(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。
sc.get(k)がif文を直接支配する場合、該処理はステップ７２１に進む。一方、sc.get(k)がif文を直接支配しない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７１９では、コンピュータ・システム（１００）は、ｉｆ文の条件節においてsc.containsKey(k)の戻り値を評価しているかどうかを判定する。sc.containsKey(k)の戻り値を評価するとは、条件節に例えば「sc.containsKey(k)==FALSE」が記載されていることをいう。ここで、メソッドcontainsKey(k)は、キー値kを指定して該キー値に対応する値が並行マップ・クラスに含まれるかどうかを返すメソッドである。sc.containsKey(k)の戻り値が評価されている場合、該処理はステップ７３１に進む。一方、評価されていない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
【００７３】
以下に、図７Ｃのステップ７２１〜７２５について説明する。
ステップ７２１では、コンピュータ・システム（１００）は、ｉｆ文がsc.put(k,v)を直接支配するかどうかを判定する。ｉｆ文がsc.put(k,v)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。ｉｆ文がsc.put(k,v)を直接支配する場合、該処理はステップ７２２に進む。一方、直接支配しない場合、該処理はステップ７２５に進む。
ステップ７２２では、コンピュータ・システム（１００）は、上記sc.get(k)の戻り値がnullと等しい場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ７２５に進む。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ７２３に進む。
ステップ７２３では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ７２４に進む。一方、メソッドが取得されなかった場合、該処理はステップ７２５に進む。
ステップ７２４では、コンピュータ・システム（１００）は、sc.get(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７２５では、コンピュータ・システム（１００）は、sc.get(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでを「if(sc.get(k)== null){synchronized(sc){」と「}}」とで囲む。上記囲むことが終了したら、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
【００７４】
以下に、図７Ｄのステップ７３１〜７３７について説明する。
ステップ７３１では、コンピュータ・システム（１００）は、sc.containsKey(k)の戻り値がfalseの場合、sc.put(k,v)が実行されるかどうかを判定する。上記「戻り値がfalseの場合にsc.put(k,v)が実行される」とは、ｉｆ文が、例えば「if(sc.containsKey(k)==false){v=sc.put(k,v);}」の場合である。sc.put(k,v)が実行される場合、該処理はステップ７３２に進む。一方、sc.put(k,v)が実行されない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７３２では、コンピュータ・システム（１００）は、sc.put(k,v)の戻り値が使用されているかどうかを判定する。sc.put(k,v)の戻り値がＣＬ内で使用されている場合、該処理はステップ７３３に進む。一方、使用されていない場合、該処理はステップ７３６に進む。
ステップ７３３では、コンピュータ・システム（１００）は、sc.containsKey(k)の戻り値がtrueの場合、戻り値が使用されるsc.get(k)があるかどうかを判定する。「戻り値が使用されるsc.get(k)がある」とは、if文が、例えば「if(sc.containsKey(k)==true){v=sc.get(k);}」の場合、vを使用するコードがＣＬに含まれていることをいう。戻り値が使用されるsc.get(k)が含まれる場合、該処理はステップ７３４に進む。一方、含まれない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７３４では、コンピュータ・システム（１００）は、sc.get()及びsc.put()から２つを後支配する位置までに実行される文があるかどうかを判定する。sc.get()及びsc.put()から２つを後支配する位置とは、sc.get()が実行された後に必ず実行される命令と、sc.put()が実行された後に必ず実行される命令とのうち、最初に共通で実行される命令のコードの位置である。実行される文がない場合、該処理はステップ７３５に進む。一方、実行される文がある場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７３５では、コンピュータ・システム（１００）は、sc.containsKey(k)がif文を直接支配するかどうかを判定する。sc.containsKey(k)がif文を直接支配するとは、if文が実行される前に必ずsc.containsKey(k)が実行され、且つsc.containsKey(k)が実行されてからif文が実行される間に必ず実行される命令が存在しないことをいう。
sc.containsKey(k)がif文を直接支配する場合、該処理はステップ７４１に進む。一方、sc.containsKey(k)がif文を直接支配しない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７３６では、コンピュータ・システム（１００）は、sc. containsKey(k)の戻り値がtrueの場合、実行される文がないかどうかを判定する。上記戻り値がtrueの場合、実行される文がないとは、if文が、例えば「if(sc.containsKey(k)==true){//nop}」の場合である。実行される文がない場合、該処理はステップ７３７に進む。一方、実行される文がある場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７３７では、コンピュータ・システム（１００）は、sc.containsKey(k)がif文を直接支配するかどうかを判定する。sc.containsKey(k)がif文を直接支配する場合、該処理はステップ７４６に進む。一方、sc.containsKey(k)がif文を直接支配しない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
【００７５】
以下に、図７Ｅのステップ７４１〜７４６について説明する。
ステップ７４１では、コンピュータ・システム（１００）は、ｉｆ文がsc.put(k,v)及びsc.get(k)を直接支配するかどうかを判定する。ｉｆ文がsc.put(k,v) 及びsc.get(k)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にsc.put(k,v)及びsc.get(k)が含まれていることをいう。ｉｆ文がsc.put(k,v)及びsc.get(k)を直接支配する場合、該処理はステップ７４２に進む。一方、ｉｆ文がsc.put(k,v)及びsc.get(k)を直接支配しない場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７４２では、コンピュータ・システム（１００）は、上記sc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ７４３に進む。
ステップ７４３では、コンピュータ・システム（１００）は、上記sc.containskey(k)の戻り値がtrueの場合に実行されるコード部分において、sc.get(k)の後にも実行文があるかどうかを判定する。sc.get(k)の後にも実行文がある場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。一方、sc.get(k)の後に実行文がない場合、該処理はステップ７４４に進む。
ステップ７４４では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ７４５に進む。一方、メソッドが取得されなかった場合、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７４５では、コンピュータ・システム（１００）は、sc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７４６では、コンピュータ・システム（１００）は、ｉｆ文がsc.put(k,v)を直接支配するかどうかを判定する。ｉｆ文がsc.put(k,v)を直接支配するとは、ｉｆ文によって選択制御されるコード部分にsc.put(k,v)が含まれていることをいう。ｉｆ文がsc.put(k,v)を直接支配する場合、該処理はステップ７４７に進む。一方、ｉｆ文がsc.put(k,v)を直接支配しない場合、該処理はステップ７５０に進む。
ステップ７４７では、コンピュータ・システム（１００）は、上記sc.containskey(k)の戻り値がfalseの場合に実行されるコード部分において、sc.put(k,v)の後にも実行文があるかどうかを判定する。sc.put(k,v)の後にも実行文がある場合、該処理はステップ７５０に進む。一方、sc.put(k,v)の後に実行文がない場合、該処理はステップ７４８に進む。
ステップ７４８では、コンピュータ・システム（１００）は、get()/put()を原子的に実行するメソッドが用意されているかどうかを判定する。コンピュータ・システム（１００）は、対応テーブル（１０７）を、例えばクラス名（java.util.Hashtable）で検索する。該検索により、get()/put()を原子的に実行するメソッドが取得された場合、該処理はステップ７４９に進む。一方、メソッドが取得されなかった場合、該処理はステップ７５０に進む。
ステップ７４９では、コンピュータ・システム（１００）は、sc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをv=sc.putIfAbsent(k,v)に置き換える。ここで置き換えられるメソッドは、上記検索により取得されたget()/put()を原子的に実行するメソッドである。置き換えが終了したら、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
ステップ７５０では、コンピュータ・システム（１００）は、sc.containsKey(k)からｉｆ文の条件が成り立った場合及び成り立たない場合のコードまでをif ((v = sc.get(key)) == null) { synchronized(sc) { if ((v =sc.get(key)) == null) { v = sc.put(key, value); } } }で置き換える。上記置き換えることが終了したら、該処理はステップ７１１に戻り、別のsc.put(k,v)についての処理を開始する。
【００７６】
図７Ｆ〜図７Ｊの各図は、本発明の実施態様における、図７Ａのステップ７０３における処理の詳細フローを示す。
なお、以下の図７Ｆ〜図７Ｊの説明において、ＳＢ１、ＳＢ２及びＳＢ３はそれぞれ異なる同期ブロックを示す。
ステップ７０３では、コンピュータ・システム（１００）は、同期ブロック（以下、ＳＢ１）の修正を行う。コンピュータ・システム（１００）は、ＳＢ１に対して以下の各処理（図７Ｆ〜図７Ｊ）を行う。
【００７７】
図７Ｆは、本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下でＳＢ１を除去する処理のフローを示す。
ステップ７５１は、図７Ａのステップ７０３の始まりを示す。
ステップ７５２では、コンピュータ・システム（１００）は、ＳＢ１内に並行マップ・クラスのインスタンスscに属するメソッド呼び出しが１つ以下あるかどうかを判定する。１つ以下あるとは、１つ含まれるか又は含まれないことである。ここで、コンピュータ・システム（１００）は、上記ステップ７０２で書き換えられた結果に含まれているインスタンスscに属するメソッド呼び出しのコードについては、それぞれを１つと数えず、上記書き換えられた結果に含まれているインスタンスscに属するメソッド呼び出しのコード全体を１つのメソッド呼び出しのコードと数える。
上記数えられたメソッド呼び出しの数が１つ以下の場合、該処理はステップ７５３に進む。一方、上記数えられたメソッド呼び出しのコード数が２つ以上の場合、該処理はステップ７６１に進む。
ステップ７５３では、コンピュータ・システム（１００）は、ＳＢ１内にインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、インスタンス変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。インスタンス変数にアクセスするコードが含まれている場合、該処理はステップ７６１に進む。一方、インスタンス変数にアクセスするコードが含まれていない場合、該処理はステップ７５４に進む。
ステップ７５４では、コンピュータ・システム（１００）は、ＳＢ１内にスタティック変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、スタティック変数にアクセスするコードが、ＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ７６１へ進む。一方、上記スタティック変数にアクセスするコードが含まれている場合、該処理はステップ７５５に進む。
ステップ７５５では、コンピュータ・システム（１００）は、ＳＢ１を除去する。上記除去は、コンピュータ・システム（１００）が、コードからＳＢ１についての記述を削除し又はコメント化することである。コメント化するとは、記述されている処理を実行できない状態にする ことである。上記ロック除去が終了することに応じて、該処理はステップ７５６へ進み、ステップ７０３は終了する。
上記ステップ７５１〜７５５の処理によって、ロック衝突の機会が減少する。
【００７８】
図７Ｇは、本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下でＳＢ１を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ７６１では、コンピュータ・システム（１００）は、ＳＢ１内にv = sc.get()が１つだけ存在するかどうかを判定する。コンピュータ・システム（１００）は、ＳＢ１で囲まれているインスタンスscからのgetメソッド呼び出し（v =sc.get()）のコードの数を数える。ここで、vは、getメソッドの戻り値を示す。また、getメソッドには、任意の引数が含まれてもよい。上記getメソッドの数が１つの場合、該処理はステップ７６２に進む。一方、上記getメソッドの数が０又は２以上の場合、該処理はステップ７７１に進む。
ステップ７６２では、コンピュータ・システム（１００）は、戻り値がv=nullのチェックを行っているかどうかを判定する。コンピュータ・システム（１００）は、上記戻り値vについてのnullチェックをするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。nullチェックは、例えば、if(v==null)である。上記nullチェックをするコードが含まれている場合、該処理はステップ７６３に進む。一方、上記nullチェックをするコードが含まれていない場合、該処理はステップ７７１に進む。
ステップ７６３では、コンピュータ・システム（１００）は、v=nullが成り立つ場合に実行されるパス内に、スタティック変数又はインスタンス変数へのアクセスが合計２回以上あるかどうかを判定する。コンピュータ・システム（１００）は、上記nullチェックにおいて戻り値がnullの場合に実行されるパス内を精査する。上記パスは、例えば、nullチェックがif(v==null)であれば、ifブロックに囲まれた範囲である。上記パス内に、インスタンス変数又はスタティック変数にアクセスするコードが合計２回以上ある場合、該処理はステップ７６４に進む。一方、上記アクセスするコードが０または１回ある場合、該処理はステップ７７１に進む。
ステップ７６４では、コンピュータ・システム（１００）は、ＳＢ１の外側にif((v=sc.get()) == null)を複製する。該処理が終了することに応じて、該処理はステップ７６５に進む。ステップ７６５は、ステップ７０５の終了を示す。
上記ステップ７６１〜７６５の処理によって、ロック衝突時間が短縮される。
【００７９】
図７Ｈ、図７Ｉ及び図７Ｊの各図は、本発明の実施態様における、図７Ａのステップ７０３における処理であり、所定の要件の下で、ＳＢ１のロックをリード・ロックに置き換え、ブロックＳＢ１の内部にある他の同期ブロックをライト・ロックに更に置き換える処理のフローを示す。
【００８０】
以下に、図７Ｈのステップ７７１〜７７６について説明する。
ステップ７７１では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ７７６に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ７７２に進む。
ステップ７７２では、コンピュータ・システム（１００）は、ＳＢ１内にプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートなスタティック変数又はプライベートなインスタンス変数への書き込みコードがＳＢ１に囲まれた範囲に含まれているかどうかを調べる。上記書き込みコードが含まれている場合、該処理は、ステップ７７６に進み終了する。一方、上記書き込みコードが含まれていない場合、該処理はステップ７７３に進む。
ステップ７７３では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているインスタンスscに属する参照に関するメソッド呼び出しのコードの数（Ｍ）を数える。インスタンスscに属する参照に関するメソッドとは、スレッド間で共有される値を取得するメソッドのことをいう。
ステップ７７４では、コンピュータ・システム（１００）は、ＳＢ１に囲まれた範囲に含まれているプライベートなスタティック変数の読み込みコードの数とプライベートなインスタンス変数の読み込みコードの数との合計値（Ｎ）を求める。
ステップ７７５では、コンピュータ・システム（１００）は、Ｍ＋Ｎ＞＝２が成り立つかどうかを判定する。コンピュータ・システム（１００）は、Ｍ＋Ｎを計算する。Ｍ＋Ｎが２以上の場合、該処理はステップ７８１に進む。一方、Ｍ＋Ｎが１以下の場合、該処理はステップ７７６に進み、終了する。
【００８１】
以下に、図７Ｉのステップ７８１〜７８６について説明する。
ステップ７８１では、コンピュータ・システム（１００）は、ＳＢ１でアクセスがあるscについての更新に関する呼び出しが、ＣＬ内にも存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査によって、ＳＢ１に囲まれた範囲に含まれているインスタンスscに属する更新に関するメソッド呼び出しに対応する、インスタンスscに属する更新に関するメソッド呼び出しのコードがＣＬ内に発見された場合、該処理はステップ７８２に進む。一方、発見されなかった場合、該処理はステップ７８５に進む。ここで、scに属する更新に関するメソッド呼び出しとは、例えば、sc.put()である。
ステップ７８２では、コンピュータ・システム（１００）は、発見された更新に関する呼び出しが第２の同期ブロック（以下、ＳＢ２）で囲まれているかどうかを判定する。コンピュータ・システム（１００）は、上記発見されたコードが、ＳＢ２で囲まれた範囲に含まれているかを調べる。含まれている場合、該処理はステップ７８３に進む。一方、含まれていない場合、該処理はステップ７８５に進む。
ステップ７８３では、コンピュータ・システム（１００）は、ＳＢ２内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ２に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ７８５に進む。一方、上記アクセスするコードが含まれていない場合、該処理はステップ７８４に進む。
ステップ７８４では、コンピュータ・システム（１００）は、ＳＢ１のロックをリード・ロックに置き換える。また、コンピュータ・システム（１００）は、ＳＢ２のロックをリード・ロックに置き換える。上記置き換えが終了すると、該処理はステップ７８５に進む。
ステップ７８５では、コンピュータ・システム（１００）は、ステップ７７４で求めた合計値（Ｎ）を判定する。Ｎ＞０の場合、ステップ７８７に進む。一方、Ｎ＞０以外の場合、該処理はステップ７８６に進み、終了する。
ステップ７８７では、コンピュータ・システム（１００）は、ＳＢ１内で発見されたプライベートなスタティック変数又はプライベートなインスタンス変数への書き込みがＣＬ内に存在するかどうかを判定する。コンピュータ・システム（１００）は、上記ＳＢ１を含むクラスのコード全体を精査する。該精査により、ＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数又はＳＢ１に囲まれた範囲で読み込みが行われているプライベートなスタティック変数を更新するコードが、ＣＬ内に発見された場合、該処理はステップ７８８に進む。一方、発見されなかった場合、該処理はステップ７９２に進み、終了する。
ステップ７８８では、コンピュータ・システム（１００）は、発見された更新が第３の同期ブロック（以下、ＳＢ３）で囲まれているかどうかを判定する。コンピュータ・システム（１００）は、上記発見されたコードが、ＳＢ３で囲まれた範囲に含まれているかを調べる。上記発見されたコードがＳＢ３に含まれている場合、該処理はステップ７８９に進む。一方、含まれていない場合、該処理はステップ７９２に進み、終了する。
ステップ７８９では、コンピュータ・システム（１００）は、ＳＢ３内にプライベートではないスタティック変数又はプライベートではないインスタンス変数へのアクセスがあるかどうかを判定する。コンピュータ・システム（１００）は、プライベートではないスタティック変数又はプライベートではないインスタンス変数にアクセスするコードがＳＢ３に囲まれた範囲に含まれているかどうかを調べる。上記アクセスするコードが含まれている場合、該処理はステップ７９２に進み、終了する。一方、上記アクセスするコードが含まれていない場合、該処理はステップ７９０に進む。
ステップ７９０では、コンピュータ・システム（１００）は、ＳＢ１のロックがリード・ロックに置き換わっていないならば、ＳＢ１の該ロックをリード・ロックに置き換える。
ステップ７９１では、コンピュータ・システム（１００）は、ＳＢ３のロックをライト・ロックに置き換える。
ステップ７９２及び７９３のいずれも、ステップ７０３の終了を示す。
【００８２】
図８Ａは、本発明の実施態様における、図７Ａのステップ７０２におけるコード変換の例を示す。
図８Ａは、第１のコードと第２のコードとの対応を示す。コード（８０１）及びコード（８０２）は、第１のコードの例である。コード（８０３）及びコード（８０４）は、第２のコードの例である。
コンピュータ・システム（１００）は、コード（８０１）及びコード（８０２）それぞれについて、図７Ａのステップ７０２（詳細には、図７Ｂ〜図７Ｅの各ステップ）の処理を行う。該処理により、コード（８０１）及びコード（８０２）は、コード（８０３）又はコード（８０４）に書き換えられる。ここで、scがメソッド（get()/put()）の組を原子的に実行するputIfAbsent()メソッドを持っている並行マップ・クラスのインスタンスである場合、コード（８０１）及びコード（８０２）は、コード（８０３）に変換される。putIfAbsent()メソッドを持っていない並行マップ・クラスのインスタンスである場合、コード（８０１）及びコード（８０２）は、コード（８０４）に変換される。
【００８３】
図８Ｂは、本発明の実施態様における、図１に示すメモリ（１０２）内にある変換前の第１のＪａｖａコード（１０８）であるＣＬ（クラスＺ）を示す。
図８Ｃ、本発明の実施態様における、図１に示すメモリ（１０２）内にある変換後の第２のＪａｖａコードであるＣＬ（クラスＺ）を示す。
以下に、図８Ｂに示す変換前の第１のＪａｖａコードであるＣＬ（クラスＺ）を、図７Ａに示す変換処理を適用して、図８Ｃに示す変換後の第２のＪａｖａコードであるＣＬ（クラスＺ）に変換する例を示す。
【００８４】
クラスＺは、図８Ｂの第１行目のクラス宣言に継承予約語extendsがないので図２のステップ２０１の条件を満たさず、キーとしてスレッド固有の値を使用していないので図２のステップ２０４の条件を満たさず、ステップ２０３の条件を満たすので、ステップ２０６で処理が行われる。ステップ２０６の処理は、下記の手順で行われる。 
【００８５】
コンピュータ・システム（１００）は、図７Ａのステップ７０１に従い、図８Ｂの「Hashtable ht = new Hashtable();」（//Z01）を図８Ｃの「ConcurrentMap ht = new ConcurrentMap();」（//Z’01）のように置き換える。
ステップ７０２では、このＣＬでは書き換えられるコードはない。
ステップ７０３では、同期ブロック（//Z07〜//Z12）に囲まれた中に、同期クラスから生成されるインスタンス変数htに関する参照メソッド呼び出しが２つ（ht.keys()とht.get()）あり、同期ブロックをリード・ロック（read lock）で置き換える。さらに、htに関する更新メソッド呼び出し（ht.put()）が//Z03にあるので、同期ブロックをライト・ロック（write lock）で置き換える。以上の変換の結果が、図８Ｃである。
【００８６】
図９は、コード変換の適用前と、本発明の実施態様におけるコード変換の適用後との性能比較の結果の一例を示す。
図９は、スループット比、ＣＰＵ使用率比及び性能向上比の各項目を示す。この性能比較のためのJava実行環境は、WebSphere Enterprise Service Bus 6.1（商標）及びJava Developers Kit（商標）を用い、ＳＵＮ（商標）のNiagara２（商標）（６４個のハードウェアスレッドを持つＣＰＵ）上で性能比較を実行した。
【００８７】
なお、上記の説明では、本発明を用いてコードを自動変換できることを示した。さらに、本発明の上記自動変換を統合開発環境（ＩＤＥ；Integrated Development Environment）に実装して、ユーザが書いたコードにマルチスレッド動作上で、例えばロック衝突の問題が発生する可能性があることをユーザに示唆することも可能である。また、本発明の上記自動変換をＩＤＥに実装し、自動で変換コードを生成する代わりに、変換コードの候補をユーザへ提示（すなわち、フィードバック）するという実装も可能である。
【００８８】
図１０は、本発明の実施態様における、図１のシステムが有するコンピュータ・ハードウェアのブロック図を示す。
本発明の実施形態に係るコンピュータ・システム（１００１）は、ＣＰＵ（１００２）とメイン・メモリ（１００３）と含み、これらはバス（１００４）に接続されている。ＣＰＵ（１００２）は好ましくは、３２ビット又は６４ビットのアーキテクチャに基づくものであり、例えば、インテル社のＸｅｏｎ（商標）シリーズ、Ｃｏｒｅ（商標）シリーズ、Ａｔｏｍ（商標）シリーズ、Ｐｅｎｔｉｕｍ（商標）シリーズ、Ｃｅｌｅｒｏｎ（商標）シリーズ、ＡＭＤ社のＰｈｅｎｏｍ（商標）シリーズ、Ａｔｈｌｏｎ（商標）シリーズ、Ｔｕｒｉｏｎ（商標）シリーズ及びＳｅｍｐｒｏｎ（商標）などを使用することができる。バス（１００４）には、ディスプレイ・コントローラ（１００５）を介して、ＬＣＤモニタなどのディスプレイ（１００６）が接続されている。ディスプレイ（１００６）は、コンピュータ・システムの管理のために、通信回線を介してネットワークに接続されたコンピュータ・システムについての情報と、そのコンピュータ・システム上で動作中のソフトウェアについての情報を、適当なグラフィック・インターフェースで表示するために使用される。バス（１００４）にはまた、ＩＤＥ又はＳＡＴＡコントローラ（１００７）を介して、ハードディスク又はシリコン・ディスク（１００８）と、ＣＤ−ＲＯＭ、ＤＶＤドライブ又はＢｌｕ−ｒａｙドライブ（１００９）が接続されている。
【００８９】
ハードディスク（１００８）には、オペレーティング・システム、Ｊ２ＥＥなどのＪａｖａ（商標）処理環境を提供するプログラム、その他のプログラム及びデータが、メイン・メモリ（１００３）にロード可能なように記憶されている。
【００９０】
ＣＤ−ＲＯＭ、ＤＶＤ又はＢｌｕ−ｒａｙドライブ（１００９）は、必要に応じて、ＣＤ−ＲＯＭ、ＤＶＤ−ＲＯＭ又はＢｌｕ−ｒａｙディスクからプログラムをハードディスクに追加導入するために使用される。バス（１００４）には更に、キーボード・マウスコントローラ（１０１０）を介して、キーボード（１０１１）及びマウス（１０１２）が接続されている。
【００９１】
通信インタフェース（１０１４）は、例えばイーサネット（商標）・プロトコルに従う。通信インタフェース（１０１４）は、通信コントローラ（１０１３）を介してバス（１００４）に接続され、コンピュータ・システム及び通信回線（１０１５）を物理的に接続する役割を担い、コンピュータ・システムのオペレーティング・システムの通信機能のＴＣＰ／ＩＰ通信プロトコルに対して、ネットワーク・インターフェース層を提供する。なお、通信回線は、有線ＬＡＮ環境、或いは例えばＩＥＥＥ８０２．１１ａ／ｂ／ｇ／ｎなどの無線ＬＡＮ接続規格に基づく無線ＬＡＮ環境であってもよい。
【００９２】
図１１は、特許請求の範囲に記載の発明の理解を容易にするための図を示す。
請求項１及び１５は、第１のプログラム・コードを第２のプログラム・コードに変換する方法の発明を記載する。請求項１及び１５の発明は、例えば本発明の実施態様における図２によって実現される。
請求項２〜７は、上記変換の対象が第１のクラスである場合の変換の方法の発明を記載する。請求項２の発明は、例えば本発明の実施態様における図２のステップ２０６及びその詳細である図７Ａによって実現される。請求項３の発明は、例えば本発明の実施態様における図２のステップ２０６及びその詳細である図７Ａのステップ７０３によって実現される。請求項４〜６の発明は、例えば本発明の実施態様における図２のステップ２０６及びその詳細である図７Ａのステップ７０３に含まれる各処理によって実現される。請求項７の発明は、例えば本発明の実施態様における図２のステップ２０６及びその詳細である図７Ａのステップ７０２によって実現される。
請求項８〜１４は、上記変換の対象が第２のクラスである場合の変換の方法の発明を記載する。請求項８の発明は、例えば本発明の実施態様における図２のステップ２０２及びその詳細である図３Ａによって実現される。請求項９の発明は、例えば本発明の実施態様における図２のステップ２０２及びその詳細である図３Ａのステップ３０５によって実現される。請求項１０〜１２の発明は、例えば本発明の実施態様における図２のステップ２０２及びその詳細である図３Ａのステップ３０５の各処理によって実現される。請求項１３の発明は、例えば本発明の実施態様における図２のステップ２０２及びその詳細である図３Ａのステップ３０２によって実現される。請求項１４の発明は、例えば本発明の実施態様における図２のステップ２０２及びその詳細である図３Ａのステップ３０３によって実現される。
請求項１６は、上記変換の対象がスレッド固有の値をキーとするメソッド呼び出しを含むクラスである場合の変換の方法の発明を記載する。請求項１６の発明は、例えば本発明の実施態様における図２のステップ２０５によって実現される。
【図１】
2010205170.tif 000003
【図２】
2010205170.tif 000004
【図３Ａ】
2010205170.tif 000005
【図３Ｂ】
2010205170.tif 000006
【図３Ｃ】
2010205170.tif 000007
【図３Ｄ】
2010205170.tif 000008
【図３Ｅ】
2010205170.tif 000009
【図３Ｆ】
2010205170.tif 000010
【図３Ｇ】
2010205170.tif 000011
【図３Ｈ】
2010205170.tif 000012
【図３Ｉ】
2010205170.tif 000013
【図３Ｊ】
2010205170.tif 000014
【図４Ａ】
2010205170.tif 000015
【図４Ｂ】
2010205170.tif 000016
【図４Ｃ】
2010205170.tif 000017
【図５Ａ】
2010205170.tif 000018
【図５Ｂ】
2010205170.tif 000019
【図５Ｃ】
2010205170.tif 000020
【図５Ｄ】
2010205170.tif 000021
【図５Ｅ】
2010205170.tif 000022
【図５Ｆ】
2010205170.tif 000023
【図６Ａ】
2010205170.tif 000024
【図６Ｂ】
2010205170.tif 000025
【図７Ａ】
2010205170.tif 000026
【図７Ｂ】
2010205170.tif 000027
【図７Ｃ】
2010205170.tif 000028
【図７Ｄ】
2010205170.tif 000029
【図７Ｅ】
2010205170.tif 000030
【図７Ｆ】
2010205170.tif 000031
【図７Ｇ】
2010205170.tif 000032
【図７Ｈ】
2010205170.tif 000033
【図７Ｉ】
2010205170.tif 000034
【図７Ｊ】
2010205170.tif 000035
【図８Ａ】
2010205170.tif 000036
【図８Ｂ】
2010205170.tif 000037
【図８Ｃ】
2010205170.tif 000038
【図９】
2010205170.tif 000039
【図１０】
2010205170.tif 000040
【図１１】
2010205170.tif 000041