質問: (Display)cls.newInstance(); } catch (ClassNotFoundException e) { throw new RuntimeException(classname + " is not found"); } catch (IllegalAccessException e) { throw new RuntimeException(classname + " cannot be accessed."); } catch (InstantiationException e) { throw new RuntimeException(classname + " cannot be instantiated."); } } return obj; } } public void display(String msg) { System.out.println("Display: " + msg); } } ``` こちらのコードは http://www.hyuki.com/techinfo/singleton.html を参考にしています。 回答お願いします。
回答: > > よって、対象インスタンスのロックを獲得しているスレッドのみが対象インスタンスのメンバにアクセスできるのだと考えています。 > > > 違います。 synchronized 自身には対象オブジェクトのメンバ変数に対するアクセス制御の意味はありません。 しかし、オブジェクトへのアクセスを排他制御したい場合は、別のオブジェクトを作るのも無駄なので、一般的にそのオブジェクト自身を synchronized の対象にします。 > > しかしながら、以下のようなコードではクラス内でインスタンスを作って、それを対象インスタンスとしています。 > > これって意味あるのでしょうか? > > > あります。このオブジェクト`_lock`はクラスの static 変数なので、いわゆるシングルトンです。排他制御をオブジェクト単位ではなく、アプリケーション全体で1個としたい場合にはシングルトンを対象として synchroized します。 ただし、例に挙げられているものについては、`_classnameToInstance`という別のシングルトンを持っているので、これを synchronized の対象にしても実装できてると思いますので、シングルトンの排他制御の例としてはいまいちだと思います。 たとえば、何か重い初期化ををオンデマンドに実行するとか、Java 以外のリソースへのアクセスを排他制御したい場合などはシングルトンのロック専用オブジェクトを作ることになると思います。 **ロックの概念** ロックにはアドバイザリロックと強制ロックがあります。Java の synchronized はアドバイザリロックです。つまり、排他制御に参加するスレッドが互いに synchronized をする約束のもとに成り立っています。誰かが約束を破って synchronized をかけずにアクセスすると、オブジェクトのメンバを更新できたりして、排他制御が崩れてバグになります。 一方で、ファイルのロックなどにおいては、強制ロックが実装されている場合があります。これは、OSレベルでロックが掛かり、一つのプロセスがロックをかけると、他のプロセスからは排他制御に参加する気がなくてもアクセスできなくなります。 一般的に、強制ロックはアドバイザリロックに比べて、コストが高いです。