package workouts;
public class synchro {
private int count = 0;
public void counting() {
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread T2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
但是当引入一个synchronized方法并在下面运行方法中调用它时...输出是20000,如果你运行它多少次..有人解释上面和下面代码之间的区别
public class synchro {
private int count = 0;
public synchronized void dosinglethread(){
count++;
}
public void counting() {
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
Thread T2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
答案 0 :(得分:1)
当你说count++
时,会发生三件事:
count
的当前值count
T1和T2完全有可能获得count
的值,然后单独递增,然后返回结果,如下所示:
Timeslot T1 T2
1 count = 3 ----
2 ---- count = 3
3 3 + 1 = 4 ----
4 ---- 3 + 1 = 4
5 store 4 in count ----
6 ---- store 4 in count
现在,count++
已被调用两次,但该值仅增加了一倍。要防止这种情况,您必须使增量原子。原子意味着执行整个操作序列,或者不执行任何操作。简单地说,如果两个语句synchronized
在同一个Object
上,则它们不会交错。
在您的第二段代码中,dosinglethread()
被声明为synchronized
。这相当于:
public void dosinglethread() {
synchronized (this) {
count++;
}
}
这意味着当其中一个线程开始执行它时,它们会在synchro
实例上获取 lock 。当第二个线程也试图执行该方法时,它会看到另一个线程已经拥有this
上的锁,所以它必须等待。当第一个线程完成该方法时,它将释放锁定,然后另一个线程可以接受它。
那么为什么volatile
不起作用? volatile
变量不会导致线程等待它们可用。相反,当count
为volatile
且您致电count++
时,会发生以下情况:(代码改编自Javamex's Tutorial)
int temp;
synchronized (count) {
temp = count;
}
temp = temp + 1;
synchronized (count) {
count = temp;
}
请注意,此代码仅供参考:synchronized
不能用于基元。
很明显,线程可能仍在temp = temp + 1
暂停,给出了与不进行任何同步时相同的问题。
有关详情,请查看the tutorial I mentioned.