ホームページ  >  記事  >  Java  >  同期とは何ですか?同期の使い方は?

同期とは何ですか?同期の使い方は?

PHP中文网
PHP中文网オリジナル
2017-06-21 13:27:182320ブラウズ

同期

前書き

オペレーティング システムを学習するとき、1 つのナレッジ ポイントは一度に 1 つのプロセスでのみ操作できるリソースです。マルチスレッドは同時に動作し、同時に 1 つのリソースのみのアクセスと変更を制御することはできません。今日は、最初の方法であるスレッド同期ブロックまたはスレッド同期について説明します。メソッド (同期)

  1. 次は、synchronized キーワードの使用例を示しますsynchronized关键字的使用

线程同步方法

public class Sychor {public void insert(Thread thread) {for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName() + "输出:  " + i);
        }

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

其中输出结果为下图

同期とは何ですか?同期の使い方は?

从上面的结果可以看出这里的两个线程是同时执行insert()方法的,下面我们在原有的代码上添加synchronized关键字看看效果如何,代码如下:

public class Sychor {public synchronized void insert(Thread thread) {for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName() + "输出:  " + i);
        }

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

上面程序的同期とは何ですか?同期の使い方は?我就不列出来,自己可以试试,总之就是加上了synchronized关键字使得线程是一个一个的执行的,只有先执行完一个线程才能执行了另外一个线程。

线程同步块

当然上面的我们使用的是线程同步方法,我们可以使用线程同步块,这两个相比线程同步块更加灵活,只需要将需要同步的代码放在同步块中即可,代码如下;

public class Sychor {public void insert(Thread thread) {synchronized (this) {for (int i = 0; i < 10; i++) {
                System.out.println(thread.getName() + "输出:  " + i);
            }
            
        }
        

    }public static void main(String[] args) {final Sychor sychor = new Sychor();

        Thread t1 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        Thread t2 = new Thread() {public void run() {
                sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

从上面的代码中可以看出这种方式更加灵活,只需要将需要同步的代码方法在同步块中,不需要同步的代码放在外面

详细原因

  1. 我们知道每一个对象都有一把锁,当我们使用线程同步方法或者线程同步块的时候实际上获得是对象的唯一的一把锁,当一个线程获得了这唯一的锁,那么其他的线程只能拒之门外了,注意这里我们说是一个对象,也就是说是同一个对象,如果是不同的对象,那么就不起作用了,因为不同对象有不同的对象锁,比如我们将上面的程序改成如下:

public class Sychor {public void insert(Thread thread) {synchronized (this) {for (int i = 0; i < 10; i++) {
                System.out.println(thread.getName() + "输出:  " + i);
            }
        }

    }public static void main(String[] args) {//第一个线程Thread t1 = new Thread() {public void run() {
                Sychor sychor = new Sychor();   //在run() 方法中创建一个对象sychor.insert(Thread.currentThread());
            };
        };//第二个线程Thread t2 = new Thread() {public void run() {
                Sychor sychor = new Sychor();  //创建另外的一个对象sychor.insert(Thread.currentThread());
            };
        };

        t1.start();
        t2.start();
    }
}

从上面的结果可知,此时线程同步块根本不起作用,因为他们调用的是不同对象的insert方法,获得锁是不一样的

  1. 上面我们已经说过一个对象有一把锁,线程同步方法和线程同步块实际获得的是对象的锁,因此线程同步块的括号中填入的是this,我们都知道this在一个类中的含义

  1. 一个类也有唯一的一把锁,我们前面说的是使用对象调用成员方法,现在如果我们要调用类中的静态方法,那么我们可以使用线程同步方法或者同步块获得类中的唯一一把锁,那么对于多个线程同时调用同一个类中的静态方法就可以实现控制了,代码如下:

public class Sychor {// 静态方法public static synchronized void insert(Thread thread)  
    {for(int i=0;i<10;i++)
        {
            System.out.println(thread.getName()+"输出     "+i);
        }
    }public static void main(String[] args) {//第一个线程Thread t1 = new Thread() {public void run() {
                Sychor.insert(Thread.currentThread());  //直接使用类调用静态方法};
        };//第二个线程Thread t2 = new Thread() {public void run() {
                Sychor.insert(Thread.currentThread());   //直接使用类调用静态方法};
        };

        t1.start();
        t2.start();
    }
}

注意

  1. 要想实现线程安全和同步控制,如果执行的是非static同步方法或者其中的同步块,那么一定要使用同一个对象,如果调用的是static同步方法或者其中的同步块那么一定要使用同一个类去调用

  1. 如果一个线程访问的是static同步方法,而另外一个线程访问的是非static的同步方法,此时这两个是不会发生冲突的,因为一个是类的锁,一个是对象的锁

  1. 如果使用线程同步块,那么同步块中的代码是控制访问的,但是外面的代码是所有线程都可以访问的

  1. 当一个正在执行同步代码块的线程出现了异常,那么jvm

スレッド同期メソッド

rrreee

出力結果は以下の通りです

同期とは何ですか?同期の使い方は?

上記の結果から、ここの 2 つのスレッドが insert() メソッドを同時に実行していることがわかります。次に、synchronized を元のコードに追加します。 code> キーワードを使用して効果を確認します。コードは次のとおりです。🎜🎜
rrreee
🎜🎜 実行中のコードはリストしません。上記のプログラムの結果は、自分で試すことができます。つまり、 synchronized キーワードを使用すると、スレッドが 1 つずつ実行され、最初に 1 つのスレッドが実行された場合にのみ、別のスレッドが実行されます。 🎜🎜

スレッド同期ブロック

🎜🎜 もちろん、上記のスレッド同期メソッドを使用しましたが、スレッド同期ブロックを使用することもできます。これら 2 つはスレッド同期ブロックよりも柔軟で、同期する必要があるコードのみが必要です。同期ブロックに置くだけです。コードは次のとおりです。 🎜🎜
rrreee
🎜🎜 上記のコードからわかるように、このメソッドはより柔軟です。同期する必要があるコードメソッドを追加します。同期ブロック内で、同期する必要のないコードが外側に配置されます。🎜🎜

詳しい理由

🎜🎜🎜🎜各オブジェクトが存在することがわかります。スレッド同期を使用する場合、 ロックがあります。 メソッドまたはスレッドがブロックを同期するとき、実際にはオブジェクトの唯一のロックを取得します。スレッドがこの一意のロックを取得すると、他のスレッドはシャットアウトされるだけであることに注意してください。ここでは、それがオブジェクトであると言い、つまり、それが異なるオブジェクトである場合、異なるオブジェクトは異なるオブジェクトロックを持っているため、機能しません。 たとえば、上記のプログラムを次のように変更します。以下: 🎜🎜🎜🎜
rrreee
🎜🎜上記の結果から、スレッド同期ブロックは現時点ではまったく機能していないことがわかります。これは、スレッド同期ブロックが次の挿入メソッドを呼び出しているためです。 異なるオブジェクトであり、ロックの取得も異なります🎜🎜 🎜🎜🎜🎜 オブジェクトがロックを持っていると上で述べましたが、スレッド同期メソッドとスレッド同期ブロックは実際にオブジェクトのロックを取得します。スレッド同期ブロックの括弧内は this で埋められています。クラス内の this の意味は誰もが知っています🎜🎜🎜🎜🎜🎜🎜クラスには次のようなものもあります。ユニークなロック。先ほど説明したのは、オブジェクトを使用してメンバーのメソッドを呼び出すことですが、クラス内の静的メソッドを呼び出したい場合は、スレッド同期メソッドまたは同期ブロックを使用して唯一のロックを取得できます。クラス内でロックする場合、複数のスレッドで同時に同じクラスの静的メソッドを呼び出すことで実現できます。制御されており、コードは次のとおりです: 🎜🎜🎜🎜
rrreee
🎜注意🎜🎜🎜🎜🎜 スレッドの安全性と同期制御を実現するには、実行が非staticの場合、同期メソッドまたは同期ブロックは同じオブジェクトを使用する必要があります。あるスレッドが static 同期メソッドにアクセスする場合、他のスレッドが非静的同期メソッドにアクセスする場合、この 2 つは競合しません。 1 つはクラス ロックで、もう 1 つはオブジェクト ロックであるためです🎜 🎜🎜🎜🎜🎜🎜🎜 スレッド同期ブロックを使用する場合、同期ブロック内のコードはアクセス制御されますが、外部のコードはすべてのスレッドからアクセス可能です🎜🎜🎜🎜🎜🎜🎜🎜同期されたコードブロックが実行されているとき スレッドで例外が発生した場合、jvm は現在のスレッドが占有しているロックを自動的に解放するため、デッドロックは発生しません例外へ🎜🎜🎜🎜🎜参考記事🎜🎜🎜🎜🎜🎜

以上が同期とは何ですか?同期の使い方は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。