에릭 왕 :
그들은 (다른 개체에 고정하기 때문에 제가 알기로, 자바에서 정적 동기 & A 예를 동기화 방법은 서로의 실행에 영향을주지 않습니다 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
출력에서 후에도 증가, 당신은이 개 스레드가 참으로 혼합 된 것을 볼 수 있지만, 최종 카운트가 작지 ROUND
여전히 동일합니다, 1 백만에.
그래서, 어떤 부분 내가 잘못 무엇입니까?
xingbin :
System.out.printf
이다 synchronized
는 실패한 테스트를하는 것은 보증하지 않습니다하지만,이 영향이있을 수 있습니다, 내부.
당신은 같은 간섭을 제거하는 제거 시도 할 수 있습니다 :
private static void incAndPrint() throws InterruptedException {
N++;
}
그리고 이것은 내 컴퓨터에 몇 시간 동안 테스트를 통과 :
final count: 1902
final count: 1111
final count: 1883