据我所知,在java中,静态同步&实例同步方法不会影响彼此的执行,因为它们锁定在不同的对象上(
this
实例vs
class
对象本身)。
在下面的代码中有两个子线程,一个运行实例同步方法,另一个运行静态同步方法。
++
运算符不是原子的,我希望下面的测试用例能够通过
++
被叫)
,但它总是无法通过测试
(最终计数等于时间
++
被叫)
.
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
那么,我错在哪一部分呢?