javaマルチスレッドの安全問題
複数のスレッドが同時に共有され、同じグローバル変数または静的変数が書き込みの動作をすると、データ衝突問題、すなわちスレッドセキュリティ問題が発生する可能性があります。しかし、読み操作をすると、データの衝突が発生しません。
模擬スレッドの安全問題
解決策
マルチスレッド間でsynchronizedを同期するか、ロック(lock)1を使うか、同期コードブロック
3.静的同期関数方法にstaticキーワードを加え、synchronizedキーワードを使ってクラスを修飾したり、クラス.classファイルを使ったりします。静的な同期関数で使用されるロックは、この関数が属するバイトコードファイルオブジェクトであり、get Class方法で取得できます。また、現在のクラス名でもいいです。クラス名で表します。
同期中に入れ子が同期してしまい、ロックが解除できなくなりました。同期中に入れ子が同期しないようにしてください。
模擬スレッドの安全問題
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
ticketCount--;
}
}
}
@RequestMapping("test-safe")
public void testSafe() {
SafeThread safeThread = new SafeThread();
Thread t1 = new Thread(safeThread, "thread-1");
Thread t2 = new Thread(safeThread, "thread-2");
t1.start();
t2.start();
}
結果:列車の切符は繰り返し販売されます。解決策
マルチスレッド間でsynchronizedを同期するか、ロック(lock)1を使うか、同期コードブロック
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
ticketCount--;
}
}
}
}
2.同期方法public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (this) {
// System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
// ticketCount--;
// }
sale();
}
}
private synchronized void sale() {
System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
ticketCount--;
}
}
注意:同期関数はthisロックを使用します。3.静的同期関数方法にstaticキーワードを加え、synchronizedキーワードを使ってクラスを修飾したり、クラス.classファイルを使ったりします。静的な同期関数で使用されるロックは、この関数が属するバイトコードファイルオブジェクトであり、get Class方法で取得できます。また、現在のクラス名でもいいです。クラス名で表します。
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (this) {
// System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
// ticketCount--;
// }
// sale();
sale2();
}
}
private synchronized void sale() {
System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
ticketCount--;
}
private void sale2() {
synchronized (SafeThread.class) {
System.out.println(Thread.currentThread().getName() + ", " + (50 - ticketCount + 1) + " ");
ticketCount--;
}
}
}
デッドロック問題同期中に入れ子が同期してしまい、ロックが解除できなくなりました。同期中に入れ子が同期しないようにしてください。