ホームページ  >  記事  >  Java  >  Java スレッドの安全性と同期の分析例

Java スレッドの安全性と同期の分析例

WBOY
WBOY転載
2023-04-29 20:58:05800ブラウズ

スレッドの安全性の問題

複数のスレッドが同じリソースを共有 (アクセス) する可能性があります

たとえば、同じオブジェクト、同じ変数、同じファイルにアクセスする場合

複数のスレッドが同じリソースにアクセスすると、スレッド セーフティの問題と呼ばれるデータの混乱やデータ セキュリティの問題が発生しやすくなります。

スレッド セーフティの問題はどのような状況で発生しますか。

複数のスレッドが、同じリソース

そして少なくとも 1 つのスレッドが書き込み操作を実行しています

例:

入金と出金の問題

入金と出金がそれぞれ 2 つのスレッドがあります

入金 出金
スレッド 1 残高 スレッド 2
1000 "----1000-----" 1000
1000 1000---- -》 2000
500 "-----1000-500

正解: 終了後の残高は 500 ではなく 1500 である必要があります

チケット購入の問題

2 スレッド


# スレッド 1 チケット番号 スレッド 2
1000 "---- 1000 -------" 1000
# 1000-1--- --》999
999 "-----1000-1

正解: 終了後の残高は 999 ではなく 998 である必要があります

チケット購入エラー (そうではありません)スレッド同期) 例:

public class love implements Runnable{
    private int piao=3000;//有3000张票
    public boolean sale() {//ture代表还有票;false代表没有票了
        if(piao<1) return false;
         piao--;//卖1张票
         
         //细化piao--;
         //寄存器=piao;
         //寄存器=寄存器-1;
         //piao=寄存器;
         
         String sk =Thread.currentThread().getName();//获取当前线程(买票窗口)的名字
         System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
         return piao>1;
    }
    public void run() {
         while(sale());//循环执行;直至卖完票返回false
    }
}
 
public class Main {
    public static void main(String[] a) {
        love tjlove =new love();
        for(int i=1;i<=4;i++) {//循环4次;产生4个线程(窗口)卖票
            Thread tj = new Thread(tjlove());
            tj.setName(""+i);
            tj.start();
        }
    }
}

部分的な出力結果:

Java スレッドの安全性と同期の分析例

##スレッドの安全性の問題

分析の問題
スレッド A およびB 値 17

を持つクラス内の 1 つの変数に対して 1 つの操作を実行します。最終結果は 2 です。 18

ソリューション
ロック:

プロセス: まず、スレッドA が最初にこの 17 にアクセスします。読み込んだ後、ロックして 1 を入力します。動作は 18

に変更され、ロック期間中は他のスレッドから 17 にアクセスできません。
変更後、Enter を書き込み、次にロック解除 17
次に、スレッド B がそれにアクセスし、ロックし、上記の操作を繰り返して 19 になり、ロックを解除します。
これにより、同時に 1 つのスレッドだけがアクセスすることが保証されるため、セキュリティが保証されます。前のエラーこれらのスレッドが一緒にアクセスしていることが原因でした

スレッド同期

今述べたロック操作はスレッド同期テクノロジです

スレッド同期テクノロジを使用してスレッドの安全性の問題を解決できます

Java ではスレッド同期には 2 つの方法があります:

1. 同期ステートメント

2. 同期メソッド

同期ステートメント

public class love implements Runnable{
	private int piao=3000;//本人cpu单核性能过强,数据量大些才能看到是4个线程在卖票
	public boolean sale() {
		synchronized(this) {//1个线程获取这个对象的锁,并加锁;    synchronized作用于整个语句
		//this指向当前对象
		//不能用new Object();这样会产生新的对象,产生新的锁
		//把this换成"123",效果基本一样;因为其存在常量值里,每次访问的对象一样
			if(piao<1) return false;
			piao--;
			String sk =Thread.currentThread().getName();
			System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
			return piao>0;
			}
	}
	public void run() {
		 while(sale());
	}
}

出力結果の一部:

Java スレッドの安全性と同期の分析例

synchronize(obj)の原則

1. 各オブジェクトには、関連する固有ロック (固有ロック) またはモニター ロック (モニター ロック) が関連付けられています。

2. 同期ステートメントを実行する最初のスレッドは、obj の内部ロックを取得できます。同期ステートメントのコードを実行した後、このロックを解放します

3. 1 つのスレッドが保持している限り、内部ロックが発生すると、他のスレッドは同時にこのロックを取得できなくなります。

✓ このロックを取得しようとすると、BLOCKED 状態になります。

4. 複数のスレッドがアクセスする場合同じ synchronized(obj) ステートメント

#obj は同期を実現するために同じオブジェクトである必要があります

同期メソッド

public class love implements Runnable{
    private int piao=3000;
    public synchronized boolean sale() { //synchronized作用于整个方法
            if(piao<1) return false;
            piao--;
            String sk =Thread.currentThread().getName();
            System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
            return piao>0;
    }
    public void run() {
         while(sale());
    }
}

synchronized はコンストラクターを変更できません

本質同期メソッドの数
インスタンス メソッド: 同期 (この)

静的メソッド: 同期 (クラス オブジェクト)

同期ステートメントは同期メソッドよりも柔軟です

同期ステートメントは、ロックする必要があるコード範囲を正確に制御し、BLOCKED 状態のスレッドの数を減らし、労力を最大限に活用することができます。

スレッド同期を使用するテクノロジの後は、

スレッド セーフティの問題を解決すると、プログラムの実行効率が低下します。

ロックが追加されると、待機中のスレッドが存在し、より多くのロック操作とロック解除操作が発生するためです。

したがって、使用するのは本当に必要な場合のスレッド同期テクノロジー

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

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。