Javaスレッドの同期と同期方法を詳しく解説

Y2J
リリース: 2017-05-04 09:59:31
オリジナル
1761 人が閲覧しました

この記事では、主に例を通して Java スレッドを紹介します: スレッド同期 - 同期方法。必要な友人は参照してください。

スレッド同期は、競合するリソースへのマルチスレッド 安全 アクセスを確保する手段です。

Java マルチスレッド プログラミング では、開発者は、競合するリソースとは何なのか、いつ同期を考慮する必要があるのか​​、どのように同期するのかなどを理解していないことがよくあります。もちろん、明確な答えはありません。これらの質問はありますが、同時に変更されている競合するリソースが存在するかどうか、いくつかの原則の問題を考慮する必要があります。

同期するには、特定の Java コードで次の 2 つの操作を完了する必要があります:

アクセスを競合するリソースをプライベートとしてマークします。

変数を変更するコードを同期し、同期されたキーワード同期を使用します。メソッドまたはコード。

もちろん、これが同時実行の安全性を制御する唯一の方法ではありません。


synchronized キーワードの使用手順


synchronized は非抽象メソッドのみをマークでき、メンバー変数を識別できません。


同期方法の使用を実証するために、初期信用限度額 100 万でクレジット カード アカウントを構築し、当座貸越や入金などの複数の操作をシミュレートしました。明らかに、銀行口座の User

オブジェクト は競合するリソースであり、複数の同時操作に口座メソッド oper(int x) が使用されます。 もちろん、このメソッドには同期が追加され、口座の残高は次のように設定される必要があります。プライベート変数への直接アクセスは禁止されています。

/** 
* Java线程:线程的同步 
* 
* @author leizhimin 2009-11-4 11:23:32 
*/ 
public class Test { 
  public static void main(String[] args) { 
    User u = new User("张三", 100); 
    MyThread t1 = new MyThread("线程A", u, 20); 
    MyThread t2 = new MyThread("线程B", u, -60); 
    MyThread t3 = new MyThread("线程C", u, -80); 
    MyThread t4 = new MyThread("线程D", u, -30); 
    MyThread t5 = new MyThread("线程E", u, 32); 
    MyThread t6 = new MyThread("线程F", u, 21); 
    t1.start(); 
    t2.start(); 
    t3.start(); 
    t4.start(); 
    t5.start(); 
    t6.start(); 
  } 
} 
class MyThread extends Thread { 
  private User u; 
  private int y = 0; 
   MyThread(String name, User u, int y) { 
    super(name); 
    this.u = u; 
    this.y = y; 
  } 
  public void run() { 
    u.oper(y); 
  } 
} 
class User { 
  private String code; 
  private int cash; 
  User(String code, int cash) { 
    this.code = code; 
    this.cash = cash; 
  } 
  public String getCode() { 
    return code; 
  } 
  public void setCode(String code) { 
    this.code = code; 
  } 
  /** 
   * 业务方法 
   * @param x 添加x万元 
   */ 
  public synchronized void oper(int x) { 
    try { 
      Thread.sleep(10L); 
      this.cash += x; 
      System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash); 
      Thread.sleep(10L); 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } 
  } 
  @Override 
  public String toString() { 
    return "User{" + 
        "code='" + code + '\'' + 
        ", cash=" + cash + 
        '}'; 
  } 
}
ログイン後にコピー

出力結果:

线程A运行结束,增加“20”,当前用户账户余额为:120 
线程F运行结束,增加“21”,当前用户账户余额为:141 
线程E运行结束,增加“32”,当前用户账户余额为:173 
线程C运行结束,增加“-80”,当前用户账户余额为:93 
线程B运行结束,增加“-60”,当前用户账户余额为:33 
线程D运行结束,增加“-30”,当前用户账户余额为:3
ログイン後にコピー
逆教材、同期外れの場合、つまりoper(int x)メソッドのsynchronized修飾子を削除してプログラムを実行し、その結果

线程A运行结束,增加“20”,当前用户账户余额为:61 
线程D运行结束,增加“-30”,当前用户账户余额为:63 
线程B运行结束,增加“-60”,当前用户账户余额为:3 
线程F运行结束,增加“21”,当前用户账户余额为:61 
线程E运行结束,增加“32”,当前用户账户余额为:93 
线程C运行结束,增加“-80”,当前用户账户余额为:61
ログイン後にコピー
明らかに、上記の結果は間違っています。エラーの理由は、複数のスレッドが競合するリソース u に同時にアクセスし、u の 属性

を変更したためです。

同期の重要性が目に見えてわかります。


注:


前の記事から分かるように、スレッド
が終了すると

、そのメソッドが属するオブジェクトのロックは解放されます。その特定のメソッドは、同期メソッドでスレッドをスケジュールするためにも使用できます。これらのメソッドは java.lang.Object クラスから取得されます。

void notify()  
     唤醒在此对象监视器上等待的单个线程。  
void notifyAll()  
     唤醒在此对象监视器上等待的所有线程。  
void wait()  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。  
void wait(long timeout)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。  
void wait(long timeout, int nanos)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量
ログイン後にコピー
上記の方法と組み合わせると、マルチスレッドの同期と相互排他の問題に対処することが非常に重要になります。有名なプロデューサーとコンシューマーの例は古典的な例であり、どの言語でもマルチスレッドについて学ぶ必要がある例です。

以上がJavaスレッドの同期と同期方法を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート