エリック王:
彼らは(別のオブジェクトをロックするので、私の知る限りでは、Javaで、静的な同期&インスタンス同期方法は、互いの実行に影響を与えませんthis
VSインスタンスclass
オブジェクト自身)。
次のコードで2件のサブスレッドがあり、一つは例えば同期方法、他の実行静的同期方法を実行します。
以来++
、オペレータがアトミックではないですが、私は渡すために、次のテストケースを期待しています(最終カウントが少ない時間以上でなければなりません++
と呼ばれる)が、それは常にテストに失敗(最終カウントが、時間に等しい++
と呼ばれます)。
SyncInstanceAndStaticRelationshipLearn.java
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* Relationship of instance & static synchronized method.
*
* @author eric
* @date 1/3/19 9:32 PM
*/
public class SyncInstanceAndStaticRelationshipLearn {
private static final int ROUND = 1000;
private static final int INC_THREAD_COUNT = 2;
private static final long OPTIONAL_INC_DELAY = 1; // optional increase delay,
private static int N = 0;
@Test
public void test() throws InterruptedException {
ThreadGroup tg = new ThreadGroup("runner");
new Thread(tg, () -> {
try {
new MixedCounter().batchInsSync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "ts-inst").start();
new Thread(tg, () -> {
try {
MixedCounter.batchStaticSync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "ts-static").start();
Thread[] tArr = new Thread[INC_THREAD_COUNT];
tg.enumerate(tArr); // get threads,
// wait all runner to finish,
for (Thread t : tArr) {
t.join();
}
System.out.printf("\nfinal count: %d\n", getN());
// just check the output, and can see the instance & static methods mixed,
Assert.assertTrue(getN() < INC_THREAD_COUNT * ROUND);
}
public static int getN() {
return N;
}
// increase & print,
private static void incAndPrint() throws InterruptedException {
System.out.printf("[%s] start, N: %d\n", Thread.currentThread().getName(), getN());
N++;
Thread.sleep(OPTIONAL_INC_DELAY);
System.out.printf("[%s] end, N: %d\n", Thread.currentThread().getName(), getN());
}
// batch increase & print,
private static void batchInsAndPrint() throws InterruptedException {
for (int i = 0; i < ROUND; i++) {
incAndPrint();
}
}
// mixed instance / static counter,
static class MixedCounter {
public synchronized void batchInsSync() throws InterruptedException {
batchInsAndPrint();
}
public synchronized static void batchStaticSync() throws InterruptedException {
batchInsAndPrint();
}
}
}
出力
[ts-inst] start, N: 0
[ts-static] start, N: 0
[ts-inst] end, N: 1
[ts-inst] start, N: 2
[ts-inst] end, N: 3
[ts-inst] start, N: 3
[ts-static] end, N: 2
[ts-inst] end, N: 4
[ts-inst] start, N: 4
[ts-inst] end, N: 5
[ts-inst] start, N: 5
[ts-inst] end, N: 6
[ts-inst] start, N: 6
[ts-inst] end, N: 7
[ts-inst] start, N: 7
[ts-inst] end, N: 8
[ts-inst] start, N: 8
[ts-static] start, N: 4
[ts-inst] end, N: 9
[ts-inst] start, N: 10
[ts-inst] end, N: 11
[ts-inst] start, N: 11
[ts-static] end, N: 10
...
[ts-inst] start, N: 1999
[ts-inst] end, N: 2000
final count: 2000
java.lang.AssertionError: expected [true] but found [false]
Expected :true
Actual :false
出力から、後でも増加し、あなたは2つのスレッドが実際に混入していることがわかりますが、最終的なカウントは小さくないROUND
、それはまだ同じだ、100万に。
だから、私は間違っている部分を取得していますか?
xingbin:
System.out.printf
でsynchronized
、それが失敗したテストを島嶼地区などはありませんが、それが影響している可能性があります、内部的に。
あなたは次のように、干渉を排除するためにそれらを削除しようとすることができます:
private static void incAndPrint() throws InterruptedException {
N++;
}
そして、これは私のコンピュータ上でいくつかの時間のためのテストに合格しました:
final count: 1902
final count: 1111
final count: 1883