説明: 共有データを操作するためのコードがメソッド内で完全に宣言されている場合は、このメソッドを同期してもよいでしょう
例として、チケットを販売する窓口を 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. 非静的同期メソッド、同期モニターは次のとおりです。 静的同期メソッド、同期モニターは現在のクラス自体です。
見てくれてありがとう!!!