JP4754004B2 - マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム - Google Patents

マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム Download PDF

Info

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
Application number
JP2009052560A
Other languages
English (en)
Other versions
JP2010205170A (ja
Inventor
一明 石崎
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
International Business Machines Corp
Original Assignee
International Business Machines Corp
Priority date (The priority date 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 date listed.)
Filing date
Publication date
Application filed by International Business Machines Corp filed Critical International Business Machines Corp
Priority to JP2009052560A priority Critical patent/JP4754004B2/ja
Priority to US12/715,874 priority patent/US8572584B2/en
Publication of JP2010205170A publication Critical patent/JP2010205170A/ja
Application granted granted Critical
Publication of JP4754004B2 publication Critical patent/JP4754004B2/ja
Expired - Fee Related legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/45Exploiting coarse grain parallelism in compilation, i.e. parallelism between groups of instructions
    • G06F8/458Synchronisation, 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つの中央演算処理装置(以下、CPU:Central Processing Unit)の内部に複数のCPUコアを封入したいわゆるマルチコアへのシフトが進んでいる。マルチコアは、外部的には1つのCPUでありながら、内部的には2つのCPUとして認識させられるので、主に並列処理を行わせる環境下において、CPUチップ全体での処理能力を上げ、性能向上を果たすことが可能である。マルチコアは、プロセッサが同時に実行可能なハードウェアスレッドの数を飛躍的に増加させる。例えば、SUN(商標)のNiagara2(商標)は、1CPU上で64個のスレッドを実行することが可能である。
このように、複数のスレッドを同時に実行することが可能なプロセッサ上で従来のプログラムが実行される場合、ロック衝突によるプロセッサの性能低下が問題になる。ここで、ロック衝突とは、スレッドが、排他実行が必要なクリティカル・セクションに入る際にロックを獲得した場合、他のスレッドは、そのロックが解除されるまで次のステップに進めない状態をいう。次のステップに進めないスレッドは、典型的には、スピン・ループ(spin loop)又はスリープ(sleep)状態になる。
ロック衝突が発生する原因はさまざまである。原因の1つは、プログラム・コードが、スレッドの排他実行のためにロックの獲得及び解放を行いながら動作する、いわゆるコレクション(Collection)クラス(以下、「同期コレクション・クラス」という)を使用する場合がである。該プログラム・コードは、例えば、この同期コレクション・クラスに属し、所与のキーから値への対応付けを行うマップ(Map)クラス(以下、「同期マップ・クラス」という)へアクセスするコードである。該プログラム・コードでは、同期マップ・クラスに含まれている全てのメソッドが、該同期マップ・クラスのインスタンス・オブジェクトによってロックされる。そのために、複数のスレッドが同じ同期マップ・クラスにアクセスしようすると、ロック衝突が頻繁に発生する。ロック衝突が発生すると、プロセッサは、1つのスレッドしか同時に実行できない。よって、ロック衝突は、性能上のスケーラビリティの問題を引き起こす。例えば、SUN(商標)のNiagara2(商標)上では、ロック衝突によってCPUが60%程度しか使用されなくなる。
下記非特許文献1は、上記同期コレクション・クラスの例であるハッシュ表クラス(Hashtable)を、同期を取らずに並行動作可能な並行ハッシュマップ・クラス(ConcurrentHashMap)に置き換えることができることを記載する。並行ハッシュマップ・クラスの詳細については、下記非特許文献2を参照されたい。
また、ハッシュ表クラスの使用を並行ハッシュマップ・クラスの使用に変換するために、コード中の「Hashtable」を、エディタに付属する置換機能で「ConcurrentHashMap」に単純に置換した場合、(1)同期マップ・クラス(Synchronized map class)のメソッドが、同期ブロック(synchronized block)で囲まれている場合、(2)クラスが、ハッシュ表クラス(java.util.Hashtable)を継承している場合、(3)同期マップ・クラスのキー(key)をスレッド固有の値で利用している場合、ロック衝突を減らすことができない。このような問題が生じることは、Websphere Enterprise Service Bus(商標)や Java Developers Kit(商標)のクラス内で確認されている。
Brian Gortz、"Java theory and practice: Concurrent collections classes"、2003年7月23日、インターネット(URL: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) "インターネット(URL:http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html)
ロック衝突による性能低下の問題が発生するたびに、原因を特定し、人手でプログラム・コードを修正する作業が必要である。しかし、該作業は、現存するプログラム・コードの量から考えると、多量のワークロードを必要とするので不可能に近い。従って、上記問題があらかじめ発生しそうな箇所を自動的に特定し、該箇所を自動的に修正する方法が必要とされている。
しかし、非特許文献1は、ハッシュ表クラスを並行ハッシュマップ・クラスに自動的に置き換えるアルゴリズムを記載していない。
また、上記で述べた、ハッシュ表クラスの使用を並行ハッシュマップ・クラスの使用に変換するにあたってロック衝突の問題に対応するために、同期マップ・クラスを自動的に置き換えるアルゴリズムを用意する必要がある。
本発明は、マルチスレッド上で動作するプログラムのプログラム・コード(以下、第1のプログラム・コード)をロック衝突が少ないプログラム・コード(以下、第2のプログラム・コード)に変換する方法を提供する。該方法は、コンピュータ・システムに下記ステップを実行させる。該ステップは、
上記第1のプログラム・コードをメモリ内に読み出して、ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(以下、第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(以下、第2のクラス)が上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードが上記第1のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス(以下、第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が上記第3のクラスよりも短い並行動作可能なクラス(以下、第4のクラス)のメソッド呼び出し(以下、第1のメソッド呼び出し)を含むところのクラスに変換するステップと、
上記第1のプログラム・コードが上記第2のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第2のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(以下、第2のメソッド呼び出し)を含むところのクラスに変換するステップと
を含む。
本発明はさらに、マルチスレッド上で動作するプログラムのプログラム・コード(第1のプログラム・コード)をロック衝突が少ないプログラム・コード(第2のプログラム・コード)に変換のためのコンピュータ・プログラムを実行するコンピュータ・システムを提供する。該コンピュータ・システムは、
上記第1のプログラム・コード及び上記変換のコンピュータ・プログラムを格納する記憶部と、
上記コンピュータ・プログラムを上記記憶部からメモリ内に読み出し、下記命令を実行する中央演算処理装置(CPU)であって、該命令が下記命令を含み、該命令が、
ロックによって同期を取りながら動作するクラスのメソッド呼び出しを含むクラス(第1のクラス)又はロックによって同期を取りながら動作する親クラスを継承しているクラス(第2のクラス)が上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードが上記第1のクラスを含むことに応じて、上記ロックによって同期を取りながら動作するクラス(第3のクラス)のメソッド呼び出しを含む該第1のクラスを、該第3のクラスに対応する機能を有し且つロックを獲得している区間が記第3のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(第1のメソッド呼び出し)を含むところのクラスに変換するステップと、
上記第1のプログラム・コードが上記第2のクラスを含むことに応じて、上記親クラスのメソッド呼び出しを含む該第2のクラスを、上記親クラスに対応する機能を有し且つロックを獲得している区間が上記第2のクラスよりも短い並行動作可能なクラスのメソッド呼び出し(第2のメソッド呼び出し)を含むところのクラスに変換するステップと
を含む。
本発明の1つの実施態様では、上記第1のメソッド呼び出しを含むクラスに変換するステップが、上記第1のクラスに含まれている上記第3のクラスのメソッド呼び出しを、上記第3のクラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が上記第3のクラスよりも短い並行動作可能な上記第1のメソッド呼び出しに変換するステップをさらに含む。
本発明の1つの実施態様では、上記第1のメソッド呼び出しに変換するステップが、上記第1のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、上記同期ブロックコードを削除するステップ、上記同期ブロックコードの位置を変更するステップ、又は上記同期ブロックコードに挟まれるコードを変更するステップをさらに含む。
本発明の1つの実施態様では、上記同期ブロックコードを削除するステップが、上記同期ブロックコードに挟まれるコードに、上記第1のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、上記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる。
本発明の1つの実施態様では、上記同期ブロックコードの位置を変更するステップが、
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
本発明の1つの実施態様では、上記同期ブロックコードに挟まれるコードを変更するステップが、
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
本発明の1つの実施態様では、上記第1のメソッド呼び出しに変換するステップが、上記第1のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、上記第1のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む。
本発明の1つの実施態様では、上記第2のメソッド呼び出しを含むクラスに変換するステップが、上記第2のクラスに含まれている上記親クラスのメソッド呼び出しを、上記親クラスのメソッド呼び出しに対応する機能を有し且つロックを獲得している区間が上記親クラスのメソッド呼び出しよりも短い並行動作可能な上記第2のメソッド呼び出しに変換するステップをさらに含む。
本発明の1つの実施態様では、上記第2のメソッド呼び出しに変換するステップが、上記第2のメソッド呼び出しを含むコードが同期ブロックコードに挟まれていることに応じて、上記同期ブロックコードを削除するステップ、上記同期ブロックコードの位置を変更するステップ、又は上記同期ブロックコードに挟まれるコードを変更するステップをさらに含む。
本発明の1つの実施態様では、上記同期ブロックコードを削除するステップが、上記同期ブロックコードに挟まれるコードに、上記第2のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、上記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる。
本発明の1つの実施態様では、上記同期ブロックコードの位置を変更するステップが、
上記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが上記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
上記同期ブロックコードを削除するステップと、
上記パスを新たな同期ブロックコードで挟むステップと、
上記新たな同期ブロックコードに挟まれるコードに、上記ロックを獲得しながらスレッド間で共有される値を取得するための上記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
を含む。
本発明の1つの実施態様では、上記同期ブロックコードに挟まれるコードを変更するステップが、
上記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
上記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
上記呼び出し又は上記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、上記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
を含む。
本発明の1つの実施態様では、上記第2のメソッド呼び出しに変換するステップが、上記第2のメソッド呼び出しを含むコードが所定の条件を満たすことに応じて、上記第2のメソッド呼び出しを含むコードをスレッド間で共有される値の取得及び変更を原子的に実行するためのコードに変更するステップをさらに含む。
本発明の1つの実施態様では、上記第2のメソッド呼び出しに変換するステップが、
上記親クラスで定義されているメソッドであって、上記第2のメソッド呼び出しを含むクラスで定義されていない該メソッドを、上記第2のメソッド呼び出しを含むクラスに上記親クラスと同じシグネチャで定義するステップと、
上記同じシグネチャで定義されたメソッドの実装を、上記親クラスで定義されているメソッドを呼び出すコードにするステップと
をさらに含む。
本発明の1つの実施態様では、上記方法は、コンピュータ・システムに下記ステップをさらに実行させる。該ステップは、
スレッド固有の値をキーとする上記第3のクラスのメソッド呼び出しを含む上記第1のクラスが上記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
上記第1のプログラム・コードがスレッド固有の値をキーとする上記第3のクラスのメソッド呼び出しを含むことに応じて、上記第1のクラスを、上記第3のクラスに対応する機能を有し且つ上記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
を含む。
本発明の1つの実施態様では、上記スレッド・ローカルの値を使用するクラスに変換するステップが、上記スレッド固有の値をキーとする上記第3のクラスのメソッド呼び出しを、上記第3のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換するステップをさらに含む。
本発明はさらに、コンピュータに、上記方法のいずれか1つに記載の方法の各ステップを実行させるコンピュータ・プログラムを提供する。
本発明の実施態様によれば、ロックによって同期を取るクラスにアクセスするプログラム・コードが、ロックを獲得している区間が上記ロックによって同期を取るクラスよりも短い並行動作可能なクラスにアクセスするプログラム・コードに自動的に変換される。さらに、該変換では、プログラム・コード上の同期ブロックによってロックされる範囲が自動的に狭められる。上記変換により、プログラム・コード実行時のロック衝突時間が減少し、マルチスレッド上のCPU効率の低下を防止することが可能である。
本発明の実施態様における、プログラム・コードを変換するためのシステムが有する機能を図示する機能ブロック図を示す。 本発明の実施態様における、図1に示すメモリ内にある第1のJavaコードを第2のJavaコードに変換する処理フローの概要を示す。 本発明の実施態様における、図2のステップ202における処理の詳細フローを示す。 本発明の実施態様における、図3Aのステップ304における処理の詳細フローを示す。 本発明の実施態様における、図3Aのステップ304における処理の詳細フローを示す。 本発明の実施態様における、図3Aのステップ304における処理の詳細フローを示す。 本発明の実施態様における、図3Aのステップ304における処理の詳細フローを示す。 本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下でSB1を除去する処理のフローを示す。 本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。 本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図3Aのステップ304におけるコード変換の例を示す。 本発明の実施態様における、図1に示すメモリ内にある第1のJavaコードであるCL(クラスX)を示す。 本発明の実施態様における、図1に示すメモリ内にある第2のJavaコードであるCL(クラスX)を示す。 本発明の実施態様における、図2のステップ205の詳細フローを示す。 本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下でSB1を除去する処理のフローを示す。 本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。 本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図1に示すメモリ内にある第1のJavaコードであるCL(クラスY)を示す。 本発明の実施態様における、図1に示すメモリ内にある第2のJavaコードであるCL(クラスY)を示す。 本発明の実施態様における、図2のステップ206の詳細フローを示す。 本発明の実施態様における、図7Aのステップ702における処理の詳細フローを示す。 本発明の実施態様における、図7Aのステップ702における処理の詳細フローを示す。 本発明の実施態様における、図7Aのステップ702における処理の詳細フローを示す。 本発明の実施態様における、図7Aのステップ702における処理の詳細フローを示す。 本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下でSB1を除去する処理のフローを示す。 本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。 本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理フローを示す。 本発明の実施態様における、図7Aのステップ702におけるコード変換の例である。 本発明の実施態様における、図1に示すメモリ内にある変換前の第1のJavaコードであるCL(クラスZ)を示す。 本発明の実施態様における、図1に示すメモリ内にある変換後の第2のJavaコードであるCL(クラスZ)を示す。 コード変換の適用前と、本発明の実施態様におけるコード変換の適用後との性能比較の結果の一例を示す。 本発明の実施態様における、図1のシステムが有するコンピュータ・ハードウェアのブロック図を示す。 特許請求の範囲に記載の発明の理解を容易にするための図を示す。
以下に本明細書及び特許請求の範囲で用いている語について説明をする。
本発明の実施態様において、「マルチスレッド上で動作するプログラムのプログラム・コード」とは、スレッドと呼ばれる処理単位を複数生成し、スレッド毎にCPUタイムを割り当てることで、並行して複数の処理を行なうことができるプログラムのソースコードをいう。該ソースコードは、例えばJava(商標)言語又はC言語(例えばC++)を使用して記述される。
本発明の実施態様において、「ロックによって同期を取りながら」とは、スレッド上で実行される処理がクリティカル・セクションに入り、共有データの読み書きを行う場合、ロックを獲得し又は解放することによって、排他制御を行うことをいう。クリティカル・セクションとは、コンピュータ上において、単一のリソースに対して複数の処理が同時期に実行されると破綻をきたす部分をいう。
本発明の実施態様において、「ロック衝突」とは、1つのスレッド上で実行される処理がクリティカル・セクションに入り、共有データの読み書きを行うためにロックを獲得すると、該ロックが解放されるまでは、他のスレッド上で実行される処理がロックを獲得できず実行待ちになる状態をいう。
本発明の実施態様において、「ロック衝突が少ない」とは、ロック衝突の頻度それ自身が減少する場合と、ロック衝突が発生したとしてもロック獲得からロック開放までの時間が短く、結果として他のスレッドのロック待ち、すなわちロック衝突の発生している時間が短くなる場合とを含む。ロック衝突の頻度それ自身が減少する場合とは、データ構造の工夫等によりロック機構を使わないで並行動作を可能にする場合を含む。ロック衝突が発生したとしてロック獲得からロック開放までの時間が短くなることを、ロックスコープが減少するともいう。
本発明の実施態様において、「ロックによって同期を取りながら動作するクラス」とは、ロックの獲得・解放によって同期を取りながらデータにアクセスするクラス又はインタフェース(以下、クラスという)である。本発明の実施態様では、上記クラスの一種であり、マップ(Map)インタフェース(キーから高々1つの値への対応付け(マッピング)を行う)を実装するクラスを、同期マップ・クラス(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()メソッドなどの固有のメソッドの定義が存在するが、並行ハッシュマップ・クラスには、上記固有のメソッドの定義は含まれない。
本発明の実施態様において、「ロックを獲得している区間」とは、プログラム・コード上の、ロックを獲得する命令とロックを開放する命令との間のコード部分をいう。上記区間は、例えば、同期ブロックで囲まれるコード部分である。
以下、図面に従って、本発明の実施態様を説明する。本実施態様は、本発明の好適な態様を説明するためのものであり、本発明の範囲をここで示すものに限定する意図はないことを理解されたい。また、以下の図を通して、特に断らない限り、同一の符号は、同一の対象を指す。
図1は、本発明の実施態様における、プログラム・コードを変換するためのシステムが有する機能を図示する機能ブロック図を示す。
コンピュータ・システム(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)を経てもよい。
本発明の実施態様では、第1のJavaコード(108)中で同期マップ・クラスが使われている場合に、コンピュータ・システム(100)は、対応テーブル(107)及び/又は変換用プログラム(106)にあらかじめ用意された対応を用いて、該同期マップ・クラスを上記同期マップ・クラスに対応する並行マップ・クラスに自動的に置き換える。該置き換えにより、Javaコード実行時のロック衝突が減少する。
対応テーブル(107)は、同期マップ・クラスと並行マップ・クラスとの対応が保存されたテーブルである。対応テーブル(107)には、例えば、同期マップ・クラスのアプリケーション・プログラム・インターフェース(API)と、上記同期マップ・クラスのAPIと同じ機能を提供する並行マップ・クラスのAPIであって、ロックを獲得している区間が上記同期マップ・クラスより短い並行動作可能な上記APIとの組が保存される。コンピュータ・システム(100)は、第1のJavaコード(108)中で同期マップ・クラスのAPIが使われている場合に、同期マップ・クラスのAPIと組をなす並行マップ・クラスのAPIを対応テーブル(107)から求める。これによりコンピュータ・システム(100)は、同期マップ・クラスのAPIを、該求めた並行マップ・クラスのAPIに置き換えることができる。
第1のJavaコード(108)が、以下の3種類のクラスのうちのいずれか1つを含む場合に、上記置き換えが可能である。
1.同期マップ・クラスが利用されているクラス
2.同期を取ることが明記されているコレクション・クラスを継承したクラス
同期をとることが明記されているコレクション・クラスとは、例えば、Javaクラス・ライブラリの同期ハッシュ表クラス(java.util.Hashtable)、Javaクラス・ライブラリの同期ベクトルクラス(java.util.Vector)及びJavaクラス・ライブラリの同期スタッククラス(java.util.Stack)である。
本明細書では、同期をとることが明記されているコレクション・クラスを上記同期ハッシュ表クラスとし、上記同期ハッシュ表クラスに対応する並行マップ・クラスを並行ハッシュ表クラス(concurrentHashtable)として説明する。
従って、同期ハッシュ表クラスを継承したクラスを用いた実施態様(図2のステップ202及び図3A〜図3Iの全てのステップ)は、同期を取ることが明記されているコレクション・クラスを継承したクラスでも実施可能である。
3. 同期マップ・クラスのキー(key)をスレッド固有の値で利用しているクラス
図2は、本発明の実施態様における、図1に示すメモリ内にある第1のJavaコード(108)を第2のJavaコード(110)に変換する処理フローの概要を示す。
コンピュータ・システム(図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は、変換処理の終了である。
図3Aは、本発明の実施態様における、図2のステップ202の詳細フローを示す。
図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を参照して別途説明する。
なお、図3Aの各ステップは、以下の条件を満たせば任意の順序を取ることができる。
・ステップ305は、ステップ301の後で実行されること。
・ステップ302は、ステップ301の後で実行されること。
・ステップ303は、ステップ302の後で実行されること。
・ステップ304は、ステップ302の後で実行されること。但し、ステップ304がステップ303より先に実行される場合、ステップ304がステップ303より後に実行される場合に比べ、コードの書き換えが行われる機会が減る可能性がある。
図3B〜図3Eの各図は、本発明の実施態様における、図3Aのステップ304における処理の詳細フローを示す。
以下の例では、条件式としてif文を使用しているが、条件式はif文に限らない。条件式は、言語に用意された条件判定を行うための予約語であればよく、例えばSwitch文であってもよい。
以下に、図3Bのステップ310〜319について説明する。
ステップ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)についての処理を開始する。
以下に、図3Cのステップ321〜325について説明する。
ステップ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)についての処理を開始する。
以下に、図3Dのステップ331〜337について説明する。
ステップ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)についての処理を開始する。
以下に、図3Eのステップ341〜350について説明する。
ステップ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の各図は、本発明の実施態様における、図3Aのステップ305における処理の詳細フローを示す。
なお、以下の図3F〜図3Jの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
ステップ305では、コンピュータ・システム(100)は、同期ブロック(以下、SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図3F〜図3J)を行う。
図3Fは、本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下でSB1を除去する処理のフローを示す。
ステップ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の処理によって、ロック衝突の機会が減少する。
図3Gは、本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ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の処理によって、ロック衝突時間が短縮される。
図3H、図3I及び図3Jの各図は、本発明の実施態様における、図3Aのステップ305における処理であり、所定の要件の下で、SB1のロックをリード・ロック(read lock)に置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロック(write lock)に更に置き換える処理フローを示す。
ここで、「リード・ロック」とは、書き込み動作がない限り複数のスレッドに同時に読み出し動作を許可することができるロックをいう。また、「ライト・ロック」とは、スレッドが書き込み動作を行う際に他のスレッドを排他制御するために使用するロックをいう。同期ブロックをリード・ロック又はライト・ロックに置き換えることにより、読み出し動作に不必要な排他的ロックを減らし、ロック衝突の機会が減少する。
以下に、図3Hのステップ371〜376について説明する。
ステップ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に進み、終了する。
以下に、図3Iのステップ381〜386について説明する。
ステップ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は、本発明の実施態様における、図3Aのステップ304におけるコード変換の例を示す。
図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)に変換される。
図4Bは、本発明の実施態様における、図1に示すメモリ(102)内にある第1のJavaコード(108)であるCL(クラスX)を示す。
図4Cは、本発明の実施態様における、図1に示すメモリ(102)内にある第2のJavaコード(110)であるCL(クラスX)を示す。
以下に、図4Bに示す変換前の第1のJavaコードであるCL(クラスX)を、図3Aに示す変換処理を適用して、図4Cに示す変換後の第2のJavaコードであるCL(クラスX)に変換する例を示す。
図4Bでは、クラスXに継承予約語extendsがある。クラスXの一行目「public class X extendsHashtable」は、クラスXが、ハッシュ表クラスを継承することの宣言である。よって、クラスXは、図2のステップ201(ハッシュ表クラスの継承)の条件を満たす。従って、クラスXは、図3Aの各ステップで変換処理される。
コンピュータ・システム(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に示すコードになる。
図5Aは、本発明の実施態様における、図2のステップ205の詳細フローを示す。
図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は、どちらのステップが先に実行されてもよい。
図5B〜図5Fの各図は、本発明の実施態様における、図5Aのステップ503における処理の詳細フローを示す。
ステップ503では、コンピュータ・システム(100)は、同期ブロック(SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図5B〜図5F)を行う。
なお、以下の図5B〜図5Fの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
図5Bは、本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下でSB1を除去する処理フローを示す。
ステップ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の処理によって、ロック衝突の機会が減少する。
図5Cは、本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ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の処理によって、ロック衝突時間が短縮される。
図5D、図5E及び図5Fの各図は、本発明の実施態様における、図5Aのステップ503における処理であり、所定の要件の下で、SB1のロックをリード・ロック(read lock)に置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロック(write lock)に更に置き換える処理フローを示す。
以下に、図5Dのステップ571〜576について説明する。
ステップ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に進み、終了する。
以下に、図5Eのステップ581〜586について説明する。
ステップ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に進み、終了する。
以下に、図5Fのステップ587〜593について説明する。
ステップ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の終了を示す。
図6Aは、図1に示すメモリ(102)内にある第1のJavaコード(108)であるCL(クラスY)を示す。
図6Bは、図1に示すメモリ(102)内にある第2のJavaコード(110)であるCL(クラスY)を示す。
以下に、図6Aに示す変換前の第1のJavaコードであるCL(クラスY)を、図5Aに示す変換処理を適用して、図6Bに示変換後の第2のJavaコードであるCL(クラスY)に変換する例を示す。
図6Aでは、クラスYに継承予約語extendsがない。
クラスYは、ハッシュ表クラスを継承しておらず、図2のステップ201の条件を満たさない。また、クラスYは、同期マップ・クラスが宣言されており(図6AのY00)、且つスレッド固有の値threadがキーとして使用されているので(例えば、図6AのY06)、図2のステップ203及び204の条件を満たす。よって、クラスYは、図5Aの各ステップで変換処理される。
図5Aのステップ501において、図6Aの2行目に示すように「ThreadLocal tlh = new ThreadLocal();」が宣言される(図6Bの//Y’00)。同時に、図6Aの2行目のハッシュマップによるインスタンスscの生成(コレクション・クラスの同期マップラッパーがかかっている)のコード(図6Aの//Y00))は除去されている。
次に、図5Aのステップ502によって、固有のスレッドthreadを引数に有する図6Aの//Y05、//Y10、//Y13 が書き換えられる。その結果、図6Bの//Y’05、//Y’10、//Y’13のように書き換えられる。その後、さらに、//Y04、//Y09が削除される。
図6Aでは、同期ブロックに囲まれた部分はないので、ステップ503によって書き換えられるコードはない。よって、変換後の第2のJavaコードは、図6Bに示すコードになる。
図7Aは、本発明の実施態様における、図2のステップ206の詳細フローである。図2のステップ206は、同期マップ・クラスを対応する並行マップ・クラスに変換する処理である。
ステップ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は、どちらのステップが先に実行されてもよい。
図7B〜図7Eの各図は、本発明の実施態様における、図7Aのステップ702における処理の詳細フローを示す。
以下の例では、条件式としてif文を使用しているが、条件式はif文に限らない。条件式は、言語に用意された判定を行うための予約語であればよく、例えばSwitch文であってもよい。
以下に、図7Bのステップ710〜719について説明する。
ステップ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)についての処理を開始する。
以下に、図7Cのステップ721〜725について説明する。
ステップ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)についての処理を開始する。
以下に、図7Dのステップ731〜737について説明する。
ステップ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)についての処理を開始する。
以下に、図7Eのステップ741〜746について説明する。
ステップ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の各図は、本発明の実施態様における、図7Aのステップ703における処理の詳細フローを示す。
なお、以下の図7F〜図7Jの説明において、SB1、SB2及びSB3はそれぞれ異なる同期ブロックを示す。
ステップ703では、コンピュータ・システム(100)は、同期ブロック(以下、SB1)の修正を行う。コンピュータ・システム(100)は、SB1に対して以下の各処理(図7F〜図7J)を行う。
図7Fは、本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下でSB1を除去する処理のフローを示す。
ステップ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の処理によって、ロック衝突の機会が減少する。
図7Gは、本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下でSB1を除去し、それに伴うコード変換をさらに行う処理のフローを示す。
ステップ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の処理によって、ロック衝突時間が短縮される。
図7H、図7I及び図7Jの各図は、本発明の実施態様における、図7Aのステップ703における処理であり、所定の要件の下で、SB1のロックをリード・ロックに置き換え、ブロックSB1の内部にある他の同期ブロックをライト・ロックに更に置き換える処理のフローを示す。
以下に、図7Hのステップ771〜776について説明する。
ステップ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に進み、終了する。
以下に、図7Iのステップ781〜786について説明する。
ステップ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は、本発明の実施態様における、図7Aのステップ702におけるコード変換の例を示す。
図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)に変換される。
図8Bは、本発明の実施態様における、図1に示すメモリ(102)内にある変換前の第1のJavaコード(108)であるCL(クラスZ)を示す。
図8C、本発明の実施態様における、図1に示すメモリ(102)内にある変換後の第2のJavaコードであるCL(クラスZ)を示す。
以下に、図8Bに示す変換前の第1のJavaコードであるCL(クラスZ)を、図7Aに示す変換処理を適用して、図8Cに示す変換後の第2のJavaコードであるCL(クラスZ)に変換する例を示す。
クラスZは、図8Bの第1行目のクラス宣言に継承予約語extendsがないので図2のステップ201の条件を満たさず、キーとしてスレッド固有の値を使用していないので図2のステップ204の条件を満たさず、ステップ203の条件を満たすので、ステップ206で処理が行われる。ステップ206の処理は、下記の手順で行われる。
コンピュータ・システム(100)は、図7Aのステップ701に従い、図8Bの「Hashtable ht = new Hashtable();」(//Z01)を図8Cの「ConcurrentMap ht = new ConcurrentMap();」(//Z’01)のように置き換える。
ステップ702では、このCLでは書き換えられるコードはない。
ステップ703では、同期ブロック(//Z07〜//Z12)に囲まれた中に、同期クラスから生成されるインスタンス変数htに関する参照メソッド呼び出しが2つ(ht.keys()とht.get())あり、同期ブロックをリード・ロック(read lock)で置き換える。さらに、htに関する更新メソッド呼び出し(ht.put())が//Z03にあるので、同期ブロックをライト・ロック(write lock)で置き換える。以上の変換の結果が、図8Cである。
図9は、コード変換の適用前と、本発明の実施態様におけるコード変換の適用後との性能比較の結果の一例を示す。
図9は、スループット比、CPU使用率比及び性能向上比の各項目を示す。この性能比較のためのJava実行環境は、WebSphere Enterprise Service Bus 6.1(商標)及びJava Developers Kit(商標)を用い、SUN(商標)のNiagara2(商標)(64個のハードウェアスレッドを持つCPU)上で性能比較を実行した。
なお、上記の説明では、本発明を用いてコードを自動変換できることを示した。さらに、本発明の上記自動変換を統合開発環境(IDE;Integrated Development Environment)に実装して、ユーザが書いたコードにマルチスレッド動作上で、例えばロック衝突の問題が発生する可能性があることをユーザに示唆することも可能である。また、本発明の上記自動変換をIDEに実装し、自動で変換コードを生成する代わりに、変換コードの候補をユーザへ提示(すなわち、フィードバック)するという実装も可能である。
図10は、本発明の実施態様における、図1のシステムが有するコンピュータ・ハードウェアのブロック図を示す。
本発明の実施形態に係るコンピュータ・システム(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)が接続されている。
ハードディスク(1008)には、オペレーティング・システム、J2EEなどのJava(商標)処理環境を提供するプログラム、その他のプログラム及びデータが、メイン・メモリ(1003)にロード可能なように記憶されている。
CD−ROM、DVD又はBlu−rayドライブ(1009)は、必要に応じて、CD−ROM、DVD−ROM又はBlu−rayディスクからプログラムをハードディスクに追加導入するために使用される。バス(1004)には更に、キーボード・マウスコントローラ(1010)を介して、キーボード(1011)及びマウス(1012)が接続されている。
通信インタフェース(1014)は、例えばイーサネット(商標)・プロトコルに従う。通信インタフェース(1014)は、通信コントローラ(1013)を介してバス(1004)に接続され、コンピュータ・システム及び通信回線(1015)を物理的に接続する役割を担い、コンピュータ・システムのオペレーティング・システムの通信機能のTCP/IP通信プロトコルに対して、ネットワーク・インターフェース層を提供する。なお、通信回線は、有線LAN環境、或いは例えばIEEE802.11a/b/g/nなどの無線LAN接続規格に基づく無線LAN環境であってもよい。
図11は、特許請求の範囲に記載の発明の理解を容易にするための図を示す。
請求項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. マルチスレッド上で動作するプログラムのプログラム・コード(以下、第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のメソッド呼び出しを含むクラスに前記親クラスと同じシグネチャで定義するステップと、
    前記同じシグネチャで定義されたメソッドの実装を、前記親クラスで定義されているメソッドを呼び出すコードにするステップと
    をさらに含む、前記方法。
  2. 前記A(1)の前記同期ブロックコードを削除するステップが、
    前記同期ブロックコードに挟まれるコードに、前記第1のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項に記載の方法。
  3. 前記A(1)の前記同期ブロックコードの位置を変更するステップが、
    前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
    前記同期ブロックコードを削除するステップと、
    前記パスを新たな同期ブロックコードで挟むステップと、
    前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
    を含む、請求項に記載の方法。
  4. 前記A(1)の前記同期ブロックコードに挟まれるコードを変更するステップが、
    前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
    前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
    前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
    を含む、請求項に記載の方法。
  5. 前記B(1)の前記同期ブロックコードを削除するステップが、
    前記同期ブロックコードに挟まれるコードに、前記第2のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項に記載の方法。
  6. 前記B(1)の前記同期ブロックコードの位置を変更するステップが、
    前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
    前記同期ブロックコードを削除するステップと、
    前記パスを新たな同期ブロックコードで挟むステップと、
    前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加するステップと
    を含む、請求項に記載の方法。
  7. 前記B(1)の前記同期ブロックコードに挟まれるコードを変更するステップが、
    前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
    前記同期ブロックコードを読み込み用ブロックコードに置き換えるステップと、
    前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更するステップと、
    を含む、請求項に記載の方法。
  8. 前記コンピュータが、
    スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含む前記第1のクラスが前記第1のプログラム・コード中に含まれているかどうかを判定するステップと、
    前記第1のプログラム・コードがスレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含むことに応じて、前記第1のクラスを、前記第3のクラスに対応する機能を有し且つ前記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換するステップと
    をさらに含む、請求項1に記載の方法。
  9. 前記スレッド・ローカルの値を使用するクラスに変換するステップが、
    前記スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換するステップをさらに含む、請求項に記載の方法。
  10. マルチスレッド上で動作するプログラムのプログラム・コード(以下、第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のメソッド呼び出しを含むクラスに前記親クラスと同じシグネチャで定義することと、
    前記同じシグネチャで定義されたメソッドの実装を、前記親クラスで定義されているメソッドを呼び出すコードにすることと
    をさらに含む、前記コンピュータ・システム。
  11. 前記A(1)の前記同期ブロックコードを削除することが、
    前記同期ブロックコードに挟まれるコードに、前記第1のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項10に記載のコンピュータ・システム。
  12. 前記A(1)の前記同期ブロックコードの位置を変更することが、
    前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第1のメソッド呼び出しと、該第1のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
    前記同期ブロックコードを削除することと、
    前記パスを新たな同期ブロックコードで挟むことと、
    前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第1のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加することと
    を含む、請求項10に記載のコンピュータ・システム。
  13. 前記A(1)の前記同期ブロックコードに挟まれるコードを変更することが、
    前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第1のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
    前記同期ブロックコードを読み込み用ブロックコードに置き換えることと、
    前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更することと、
    を含む、請求項10に記載のコンピュータ・システム。
  14. 前記B(1)の前記同期ブロックコードを削除することが、
    前記同期ブロックコードに挟まれるコードに、前記第2のメソッド呼び出しが1つ含まれるか又は含まれず、且つ、前記並行動作可能なクラスのインスタンス変数以外のインスタンス変数へのアクセス及びスタティック変数へのアクセスの少なくとも1が含まれていない場合に行われる、請求項10に記載のコンピュータ・システム。
  15. 前記B(1)の前記同期ブロックコードの位置を変更することが、
    前記同期ブロックコードに挟まれるコードが、ロックを獲得しながらスレッド間で共有される値を取得するための第2のメソッド呼び出しと、該第2のメソッド呼び出しの戻り値が所定の値である場合に実行されるパスとを含み、及び該パスが前記並行動作可能なクラスのインスタンス変数又はスタティック変数へのアクセスを2以上含む場合、
    前記同期ブロックコードを削除することと、
    前記パスを新たな同期ブロックコードで挟むことと、
    前記新たな同期ブロックコードに挟まれるコードに、前記ロックを獲得しながらスレッド間で共有される値を取得するための前記第2のメソッド呼び出しと該メソッド呼び出しの戻り値が所定の値であることの判定文とを含むコードを追加することと
    を含む、請求項10に記載のコンピュータ・システム。
  16. 前記B(1)の前記同期ブロックコードに挟まれるコードを変更することが、
    前記同期ブロックコードに挟まれるコードが、スレッド間で共有される値を取得するための第2のメソッド呼び出し、プライベートなインスタンス変数の読み出し又はプライベートなスタティック変数の読み出しから選択される2つ以上の読み出しを含む場合、
    前記同期ブロックコードを読み込み用ブロックコードに置き換えることと、
    前記呼び出し又は前記読み出しで参照される変数を変更する命令を含む他の同期ブロックコードに挟まれるコードに、前記変更する命令を挟む書き込み用ブロックコードを変更することと、
    を含む、請求項10に記載のコンピュータ・システム。
  17. 前記コンピュータが、
    スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含む前記第1のクラスが前記第1のプログラム・コード中に含まれているかどうかを判定することと、
    前記第1のプログラム・コードがスレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを含むことに応じて、前記第1のクラスを、前記第3のクラスに対応する機能を有し且つ前記スレッド固有の値を使用する代わりにスレッド・ローカルの値を使用するクラスに変換することと
    をさらに含む、請求項10に記載のコンピュータ・システム。
  18. 前記スレッド・ローカルの値を使用するクラスに変換することが、
    前記スレッド固有の値をキーとする前記第3のクラスのメソッド呼び出しを、前記第3のクラスのメソッド呼び出しに対応する機能を有するスレッド・ローカル・クラスのメソッド呼び出しに変換することをさらに含む、請求項17に記載のコンピュータ・システム。
  19. マルチスレッド上で動作するプログラムのプログラム・コード(以下、第1のプログラム・コード)をロック衝突が少ないプログラム・コード(以下、第2のプログラム・コード)に変換するコンピュータ・プログラムであって、コンピュータに、請求項1〜のいずれか1項に記載の方法の各ステップを実行させる前記コンピュータ・プログラム。
JP2009052560A 2009-03-05 2009-03-05 マルチスレッド上で動作するプログラムのプログラム・コードをロック衝突が少ないプログラム・コードに変換するための方法、並びにそのコンピュータ・プログラム及びコンピュータ・システム Expired - Fee Related JP4754004B2 (ja)

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)

* Cited by examiner, † Cited by third party
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)

* Cited by examiner, † Cited by third party
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

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