[Java マルチスレッド] 同期メソッドを使用してスレッドの安全性の問題を解決する

説明: 共有データを操作するためのコードがメソッド内で完全に宣言されている場合は、このメソッドを同期してもよいでしょう

例として、チケットを販売する窓口を 3 つ作成し、チケットの合計数が 100 であると質問してみましょう。

1: 同期メソッドを使用して、Runnable インターフェイスの実装に伴うスレッド セーフティの問題を解決する

前回の記事によると、同期されたコード ブロックを使用して、Runnable インターフェイス コードの実装に伴うスレッド セーフティの問題を解決する方法は次のとおりです。

class Window1 implements Runnable{

    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (this){//此时的this:唯一的Window1的对象 synchronized (obj) {
                if (ticket > 0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest1{
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

共有データを操作するコードをメソッドで完全に宣言します。

private synchronized void show(){
        if (ticket > 0) {
             try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
            ticket--;
        }
    }

整理すると、完全なコードは次のようになります。

class Window1 implements Runnable {

    private int ticket = 100;

    @Override
    public  void run() {
        while (true) {
            show();
        }
    }
    private synchronized void show(){
        if (ticket > 0) {
             try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

showメソッドにはデフォルトの同期モニター「this」があります

上記の方法を真似て、Threadクラスの継承方法におけるスレッドセーフ問題に対処するための同期方法を適用し、Threadクラスを継承して複数のスレッドを作成するコードでは、共有データを操作するコードを完全に記述します。メソッドで宣言された

コードは以下のように表示されます。

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    private synchronized void show(){
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(getName() + "卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {

        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

操作の結果は次のようになります。

 まだ間違ったチケットがあることがわかります。これは、上記のshow メソッドにデフォルトの同期モニター「this」があるためです。このプログラムでは、同期モニターとなる 3 つのオブジェクト (t1、t2、t3) を作成しました。ただし、複数のスレッドが同じロックを共有する必要があります (同期モニター)

show メソッドを静的に変更できます。

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    private static synchronized void show(){//同步监视器:t1,t2,t3
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {

        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

この時の同期モニターは現在のクラス -->Window.class 

================================================= == ==========================概要:

1. 同期メソッドには同期モニターが含まれますが、明示的に宣言する必要はありません。

2. 非静的同期メソッド、同期モニターは次のとおりです。 静的同期メソッド、同期モニターは現在のクラス自体です。

見てくれてありがとう!

おすすめ

転載: blog.csdn.net/qq_64976935/article/details/128891043