【发布时间】:2014-10-22 16:35:26
【问题描述】:
public class ThreadTest implements Runnable {
private int counter;
private Date mydate = new Date();
public void upCounter1() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("1 " + counter);
}
}
}
public void upCounter2() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("2 " + counter);
}
}
}
public void upCounter3() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("3 " + counter);
}
}
}
@Override
public void run() {
upCounter1();
upCounter2();
upCounter3();
}
public static void main(String[] args) {
Threadtest mtt = new Threadtest();
Thread t1 = new Thread(mtt);
Thread t2 = new Thread(mtt);
Thread t3 = new Thread(mtt);
t1.start();
t2.start();
t3.start();
}
}
我用各种同步技术尝试了这段代码,我想确保我知道发生了什么。我已经阅读了很多关于这方面的文章,但没有一篇文章对我来说足够深入。
所以这是我观察到的:
synchronised (this):这只有在我给所有线程提供相同的 Threadtest 实例时才有效,因为如果我给每个线程自己的实例,每个线程都会获得该实例的内在锁,并且可以不间断地访问方法来自其他线程。但是,如果我给每个线程自己的实例,我可以这样做:
synchronised (getClass()),因为这样我就获得了类的内在锁或者,我可以这样做:
synchronised (mydate),其中适用于同步 (this) 的相同规则。但它的优点是不公开。 > 我真的不明白这一点。使用this有什么“危险”?除了
synchronised (getClass()),我还可以使用私有静态字段。 但是,我做不到synchronised(Date.class)。我可以同步整个方法(效果与同步块相同)
使计数器 volatile 不起作用,因为递增不是真正的原子操作
如果我想让每个方法都可以单独访问,我会创建三个私有字段并在同步块中使用它们。然后我有效地使用了这些字段的内在锁,而不是我的类或实例。
我还注意到,当我使用类锁时,每个方法都被视为独立的,我实际上有 3 个计数器达到 15。如果我使用实例锁,计数器变为 45。是吗正确和预期的行为?
我的解释和观察是否正确? (我基本上是想确保从我得到的控制台输出中得出正确的结论)
【问题讨论】:
-
你还没有定义什么是“正确”的行为。您是否只想保证计数器达到其预期值?它的预期最终值是多少?您想避免交错打印语句吗?
-
抱歉回复晚了:所以,我真的没想到会有任何行为(执行计数器不交错或跳跃,这在没有同步的情况下发生)。我只是看着控制台输出然后想“啊,那个输出可能在那里,因为......”
标签: java multithreading synchronized