同期についての疑問

このQ&Aのポイント
  • あるオブジェクトの同期方法についての疑問です。
  • ケース1とケース2の違いを教えてください。
  • ケース1とケース2のgetInstanceメソッドを比較しています。
回答を見る
  • ベストアンサー

同期について

ちょっと疑問に思ったので質問させてください。 たとえばあるオブジェクトに対して同期(ここではinstance)する場合、ケース1とケース2では違いがありますでしょうか? ケース1: public static Test getInstance() {   synchronized(instance) { if(instance != null) { return instance; } else { instance = new Test(); return instance; } } ケース2: public static synchronized Test getInstance() { if(instance != null) { return instance; } else { instance = new Test(); return instance; } } 以上宜しくお願いします。

  • Java
  • 回答数1
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • bgbg
  • ベストアンサー率53% (94/175)
回答No.1

この2つは同じ機能ではありません。 ケース1ではinstanceというフィールドに対して排他制御がかかりますが、ケース2は静的オブジェクトTestに対して排他制御がかかります。 排他制御は制御対象が同じオブジェクト同士でないとかかりません。 なので、ケース1とケース2は挙動が違ってきます。 具体的には、ケース1とケース2のメソッドは互いに排他制御されません。 一般的にはケース2のようなメソッド単位で排他制御するよりもケース1のブロック単位で制御するほうが小回りが利いて使いやすいです。 なお、ブロック単位の排他制御は、synchronized文の引数オブジェクトが未定義やnullの場合はNullPointerExceptionが飛ぶので注意してください。

関連するQ&A

  • CakePHPでシングルトンパターン

    CakePHPでシングルトンパターンで、インスタンスを使いまわしたいのですが、 うまく動作しません。 以下のようなプログラムですが、何か設定が足りないのでしょうか class Test{   public static $instance = null;   public function __construct(){}   public function getInstance(){    if(is_null(Test::$instance)){     Test::$instance = new Test();    }    return Test::$instance;   } } 上記クラスを以下のように呼び出しております。 $instance = Test::getInstance(); 何度やっても、インスタンスが新しく生成されてしまします。 良い方法がございましたら、ご教授下さい。

    • ベストアンサー
    • PHP
  • C++ シングルトン マルチスレッド

    標準C++でシングルトンを実装したいのですが。 class Singleton{ public: static Singleton* getInstance(){ if (_instance == NULL){ //スレッドAがこの時点で、スレッドBがNULLチェックすると破綻する _instance = new Singleton(); } return _instance; } private: Singleton(); static Singleton* _instance; }; マルチスレッドになると上記のパターンで破綻するといわれどうしたものかと考えております。 static Singleton* _instance = new Singleton(); と出来れば解決なのですが 「static const int データメンバ以外をクラス内で初期化することはできません」 とのことでそれもできず。 どのようにすればよいでしょうか。

  • &や&=について

    --------------------------------------- class TextSanitizer { function &getInstance() { static $instance; if (!isset($instance)) { $instance = new TextSanitizer(); } return $instance; } } $myts =& TextSanitizer::getInstance(); ------------------------------------------- 上記について3点質問がございます。 1.【&getInstance()】の&は何を意味していますでしょうか? 2.【$myts =& TextSanitizer::getInstance();】の&=は何を意味していますでしょうか? 3.getInstance()関数はどんなとき使用すべきでしょうか? ご検討がつく方アドバイスを宜しくお願いします。

    • ベストアンサー
    • PHP
  • PHP T_STRINGエラー?

    新しくPHPのサイトを作成しようとしたんですが、 syntax error, unexpected '{', expecting T_STRING in と表示されてどうにも使用がありません。 どこが原因でエラーが出てるのでしょうか? エラー行は7行と表示されていますが、いまいちわかりません スクリプトは以下の記述の通りです <?php require './Request.php'; require './Cookie.php'; final class SystemMain extends { private static $instance; private $modeName; public static function getInstance() { if (self::$instance === null) { self::$instance = new SytemMain(); } return self::$instance; } public function setMode() { if (file_exists('./maintenance')) { $this->modeName = 'Maintenance'; } else { $str = Request::both('mode'); if (!$str) { $this->modeName = 'Top'; } else if (file_exists('./script/mode/' . $str . '.php')) { $this->modeName = $str; } else { $this->modeName = 'NotFound'; } } require_once './script/mode/' . $this->modeName . '.php'; } public function getMode() { return $this->modeName; } } ?> Request.php <? class Request extends { public static function get($str) { return isset($_GET[$str]) ? $_GET[$str] : null; } public static function post($str) { return isset($_POST[$str]) ? $_POST[$str] : null; } public static function both($str) { $post = self::post($str); return $post ? $post : self::get($str); } } ?> Cookie.php <? class Cookie extends { public static function set($name, $value, $expire = 0) { return setcookie($name, $value, $expire); } public static function get($str) { return isset($_COOKIE[$str]) ? $_COOKIE[$str] : null; } public static function clear($str) { $_COOKIE[$str] = ""; return setcookie($str, ""); } } ?>

    • ベストアンサー
    • PHP
  • synchronizedによる同期化について

    Javaで開発しています。 synchronizedで同期化したく、サンプルを作ってみたのですが上手く同期化が出来ていないようなので質問しました。 以下プログラム public class Synch{ public static void main(String[] args){ final Something obj = new Something(); new Thread(){ public void run(){ synchronized(this){ try{ obj.write(); } catch(Exception e){ }notify();} } }.start(); new Thread(){ public void run(){ try{ obj.read(); } catch(Exception e){ } } }.start(); } } class Something{ private int x = 10; private int y = 100; public synchronized void write(){ if(x < y){ System.out.println("write:x < y"); } else if(x > y){ System.out.println("write:x > y"); } for(int n = 0;n < 100;n++){ x++; y++; } for(int m = 0;m < 150;m++){ y--; } if(x < y){ System.out.println("write:x < y"); } else if(x > y){ System.out.println("write:x > y"); } } public synchronized void read(){ if(x < y){ System.out.println("read:x < y"); } else if(x > y){ System.out.println("read:x > y"); } } } このプログラムを実行すると、時々readのほうが先に表示されてしまいます。 実行環境はEclipse2.1.3です。 readが先に表示されるのは仕方のないことなのでしょうか? それともプログラムがいけないのでしょうか? ご存知の方いらっしゃいましたら教えて頂けないでしょうか。 不足がありましたら仰ってください。

    • ベストアンサー
    • Java
  • javaの同期について

    javaの同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました

    • ベストアンサー
    • Java
  • javaの同期について

    javaの同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました。

    • ベストアンサー
    • Java
  • DB接続について

    JAVA初心者です。 DB接続についてなのですが、いままで設定ファイルより<url>,<user>,<password>等の情報を取得してDB接続していたのですが、今後、『WebSphere』のデータソースの設定から取得する方式に変更となり、プログラム例として次のコードをもらったのですが… InitialContext ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("登録したJNDI名"); Connection conn = ds.getConnection(); これを以下のコードにどう組み込んでよいかわかりません… どうかご教授お願いします。 public class ConnectionCache{ private static final string This_Name = "jp.co.ise.filetransfer.server.common.ConnectionCache"; private static ConnectionCache instance = null; private static ObjectPool pool = null; private DataSource ds = null; // java.lang.Object#Object() private ConnectionCache(){} // Method ConnectionCache // @param ds private ConnectionCache(DataSource ds){ this.ds = ds; } // Method getDataSource // @return DataSource public static DataSource getDataSource(){ return instance.ds; } public static void init(Properties prop) throws Exception { try { class.formName(prop.getProperty("drive")); // プールするアイドルコネクション数の上限 int maxIdleNum = Integer.parselnt(prop.getProperty("maxIdle")); // プール初期化時のアイドルコネクション数 int initIdleCapacityNum = Integer.parselnt(prop.getProperty("initIdleCapacity")); // ObjectPoolインスタンスを生成 int initIdleCapacityNum = Integer.parselnt(prop.getProperty("initIdleCapacity")); // Connectionオブジェクトを生成するためのConnectionFactoryインスタンスの生成 ConnectionFactory conFactory = new DriverManagerConnectionFactory( prop.getProperty("url"), prop.getProperty("user"), prop.getProperty("password") ); // PoolableConnectionFactoryインスタンスの生成 new PoolableConnectionFactory( conFactory, pool, null, prop.getProperty("validationQuery"), true, true ); // プーリング機能を持つDataSourceインスタンスの生成 DataSource ds = new PoolingDataSource(pool); // 初期サイズ指定分のコネクションをプール ArrayList initConnections = new ArrayList(); // 新規接続 for(int i = 0; i < initIdleCapacityNum; i++){ initConnections.add(ds.getConnection()); } // プールへ返却 for(int i = 0; i < initIdleCapacityNum; i++){ ((Connection)initConnections.get(i)).close(); } instance = new AppleConnectionCache(ds); system.out.println( THIS_NAME + "DB接続プールを初期化しました。:プール内のコネクション数 = " + pool.getNumIdle()); } catch (Throwable t) { throw new Exception ( THIS_NAME + "DB接続プールの初期化に失敗しました。:" + t.getMessage()); } } //Method getInstance. //@return AppleConnectionCache public static synchronized AppleConnectionCache getInstance() { return instance; } //Method getConnection. //@return Connection public synchronized Connection getConnection() throws Exception { Connection conn = null; try{ conn = ds.getConnection(); } catch (SQLException e) { throw new Exception ( THIS_NAME + "DB接続に失敗しました。:" + e.getMessage()); } return conn; } //Method closeCache. public synchronized void closeCache() { try{ pool.close(); system.out.println(THIS_NAME + "DB接続プールのリソースを開放しました。"); } catch (Exception e) { } }

  • シングルトン内で使用したオブジェクトのGC

    基本的な質問で恐縮ですがGCについて教えてください。 例えば、シングルトンインスタンス内のhogemethodメソッドにてHashMapのインスタンスを 生成・使用した場合(以下の質問に続く)、 【質問】 hogemethodメソッドが終わればHashMapのインスタンスはスコープを外れるので、hogeMap = null;などしなくてもGC対象となり、そのうちGCされるのでしょうか?いやいや、hogeMap = null; することによりGC対象となり、そのうちGCされるのでしょうか?それとも、nullセットしようがしまいが、シングルトンのインスタンスが存在し続ける限りGC対象とはなってもGCされることは無いのでしょうか? package hoge; public class MySingleton {  private static MySingleton instance = new MySingleton();  private MySingleton() {}  public static MySingleton getInstance() {   return instance;  }  public void hogemethod() {   HashMap hogeMap = new HashMap();   hogeMap .put("りんご", "apple");   hogeMap .put("ぶどう", "grapes");     :   hogeMap = null; ←★hogeMap をGC対象にするためにはnull代入は必要なのか?  } } よろしくお願いします。

    • ベストアンサー
    • Java
  • synchronizedを使用方法で混乱しています。

    JAVAを独学で勉強しております。synchronizedをインスタンスメソッドに使用したのですが、同期化できません。いくら考えてもわからなかったので、質問しました。ソースを記入します。 class Test extends Thread{ public void run(){ ss(); } public synchronized void ss(){ for(int x=1;x<=10;x++){ System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args){ Test t1 =new Test(); Test t2 =new Test(); Test t3 =new Test(); t1.start(); t2.start(); t3.start(); } } 実行すると、同期化されてなく、ランダムに表示されます。違うオブジェクトで参照しているから、ロックかけても意味がないのかなーとも思っていますが、 Threadの拡張じゃなく、Runnableの実装に書き換えると同期化されます。なぜでしょう?自分なりに精一杯考えましたがわかりません。分かる方、説明お願いできますでしょうか?

    • ベストアンサー
    • Java

専門家に質問してみよう