我正在研究有关同步的Oracle文档,并且有这个类计数器:
-- Create tables
CREATE TABLE initialValues(
id serial PRIMARY KEY,
value int
);
CREATE TABLE addOne(
id serial,
id_init_val int REFERENCES initialValues(id),
value int
);
-- Init values
INSERT INTO initialValues(value)
SELECT a.n
FROM generate_series(1, 100) as a(n);
-- Insert values in the second table by selecting the ones from the
-- First one .
WITH init_val as (SELECT i.id,i.value FROM initialValues i)
INSERT INTO addOne(id_init_val,value)
(SELECT id,value+1 FROM init_val);
他们用两个线程解释了一些可能的错误交错,我试着写一个程序来测试这些糟糕的交错:
class Counter {
int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
但无论对c的访问是否同步,我总是得到0,0和0的值,我不知道为什么。
有人可以帮助我吗? 最好的问候。
答案 0 :(得分:2)
巧合,这是我机器上的结果:
1
0
0
Process finished with exit code 0
而且,如果你再试一次,
for (int i = 0; i < 100; i++) {
Counter counter = new Counter();
AdderCounter ac = new AdderCounter(counter);
SubberCounter sc = new SubberCounter(counter);
Thread t1 = new Thread(ac);
Thread t2 = new Thread(sc);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.c);
System.out.println();
}
你可能会得到这个:
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
-1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
1
0
0
答案 1 :(得分:2)
您需要并行运行add / sub 多次次。
private static final int COUNT = 1000000;
class Counter {
int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
class AdderCounter implements Runnable {
Counter counter;
public AdderCounter(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < COUNT; i++) {
counter.increment();
}
}
}
class SubberCounter implements Runnable {
Counter counter;
public SubberCounter(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < COUNT; i++) {
counter.decrement();
}
}
}
public void test() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Counter counter = new Counter();
AdderCounter ac = new AdderCounter(counter);
SubberCounter sc = new SubberCounter(counter);
Thread t1 = new Thread(ac);
Thread t2 = new Thread(sc);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.c);
}
}
这一次打印:
-33852
28937
-546
-678544
-653775
358351
-593183
1000000&lt; - 现在这是一个真正的巧合:)
-826735
-773183
对我来说,如果没有发生线程争用,你会期望0
。
println
语句 - 在测试时使用IO会使交错更不可能,因为大多数时候代码都在进行I / O操作
答案 2 :(得分:1)
对于并发程序中的错误,可能最糟糕的事情是它们通常不会出现。您可以在本地计算机上运行该程序数千次,它运行正常。然后你将它移动到一个服务器,这个服务器被数以百万计的人访问,并且事情开始“无缘无故”地破坏。