オペレーティング システムを学習するとき、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(); } }
从上面的代码中可以看出这种方式更加灵活,只需要将需要同步的代码方法在同步块中,不需要同步的代码放在外面
我们知道每一个对象都有一把锁,当我们使用线程同步方法或者线程同步块的时候实际上获得是对象的唯一的一把锁,当一个线程获得了这唯一的锁,那么其他的线程只能拒之门外了,注意这里我们说是一个对象,也就是说是同一个对象,如果是不同的对象,那么就不起作用了,因为不同对象有不同的对象锁,比如我们将上面的程序改成如下:
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方法,获得锁是不一样的
上面我们已经说过一个对象有一把锁,线程同步方法和线程同步块实际获得的是对象的锁,因此线程同步块的括号中填入的是
this
,我们都知道this
在一个类中的含义
一个类也有唯一的一把锁,我们前面说的是使用对象调用成员方法,现在如果我们要调用类中的静态方法,那么我们可以使用线程同步方法或者同步块获得类中的唯一一把锁,那么对于多个线程同时调用同一个类中的静态方法就可以实现控制了,代码如下:
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(); } }
要想实现线程安全和同步控制,如果执行的是非
static
同步方法或者其中的同步块,那么一定要使用同一个对象,如果调用的是static同步方法或者其中的同步块那么一定要使用同一个类去调用
如果一个线程访问的是
static
同步方法,而另外一个线程访问的是非static的同步方法,此时这两个是不会发生冲突的,因为一个是类的锁,一个是对象的锁
如果使用线程同步块,那么同步块中的代码是控制访问的,但是外面的代码是所有线程都可以访问的
当一个正在执行同步代码块的线程出现了异常,那么
jvm
スレッド同期メソッド
rrreee
上記の結果から、ここの 2 つのスレッドが
insert()
メソッドを同時に実行していることがわかります。次に、synchronized を元のコードに追加します。 code> キーワードを使用して効果を確認します。コードは次のとおりです。🎜🎜synchronized
キーワードを使用すると、スレッドが 1 つずつ実行され、最初に 1 つのスレッドが実行された場合にのみ、別のスレッドが実行されます。 🎜🎜this
で埋められています。クラス内の this
の意味は誰もが知っています🎜🎜🎜🎜🎜🎜🎜クラスには次のようなものもあります。ユニークなロック。先ほど説明したのは、オブジェクトを使用してメンバーのメソッドを呼び出すことですが、クラス内の静的メソッドを呼び出したい場合は、スレッド同期メソッドまたは同期ブロックを使用して唯一のロックを取得できます。クラス内でロックする場合、複数のスレッドで同時に同じクラスの静的メソッドを呼び出すことで実現できます。制御されており、コードは次のとおりです: 🎜🎜🎜🎜static
の場合、同期メソッドまたは同期ブロックは同じオブジェクトを使用する必要があります。あるスレッドが static
同期メソッドにアクセスする場合、他のスレッドが非静的同期メソッドにアクセスする場合、この 2 つは競合しません。 1 つはクラス ロックで、もう 1 つはオブジェクト ロックであるためです🎜 🎜🎜🎜🎜🎜🎜🎜 スレッド同期ブロックを使用する場合、同期ブロック内のコードはアクセス制御されますが、外部のコードはすべてのスレッドからアクセス可能です🎜🎜🎜🎜🎜🎜🎜🎜同期されたコードブロックが実行されているとき スレッドで例外が発生した場合、jvm
は現在のスレッドが占有しているロックを自動的に解放するため、デッドロックは発生しません例外へ🎜🎜🎜🎜🎜参考記事🎜🎜🎜🎜🎜🎜以上が同期とは何ですか?同期の使い方は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。