我是一个新手java程序员,对下面的代码片段有点困惑。这是否意味着第一个线程将与第三个线程共享锁?希望有人能帮我澄清。提前谢谢。
public class T_6 extends Thread {
static Object o = new Object();
static int counter = 0;
int id;
public T_6(int id) {
this.id = id;
}
public void run () {
if ( counter++ == 1 ) //confused in here.
o = new Object();
synchronized ( o ) {
System.err.println( id + " --->" );
try {
sleep(1000);
} catch ( InterruptedException e ) {
System.err.println("Interrupted!");
}
System.err.println( id + " <---" );
}
}
public static void main (String args []) {
new T_6(1).start();
new T_6(2).start();
new T_6(3).start();
}
}
发布于 2013-08-14 07:33:11
当你达到向上计数和如果,你做一个典型的检查,然后-行动操作。这里的问题是几个线程可以同时到达这里。这意味着他们将拥有counter
的本地副本。不同的线程可能都有一个0的本地副本--这意味着它们最多可以计数1并创建新的对象--所有这些。但是它们存储在静态容器中--它们可能有也可能没有本地副本。总之,这里发生的一切都是偶然的。它们最终可能会在同一个对象上同步--但是它们可能尝试在不同的对象上同步,这意味着它们根本不会同步。
您应该看看final
和volatile
关键字。
final
意味着一旦指向某个地方,引用就不能被重新指向。这是锁的好主意。如果您将声明更改为
final static Object o = new Object();
您可以保证o
不能更改,并且所有同步都将位于同一个对象上。
volatile
意味着VM禁止存储变量的线程本地副本。所有的读和写都必须到内存中。这意味着所有线程都会看到其他线程所做的写操作。
发布于 2013-08-14 07:16:23
为了确保多个线程之间正确的同步,所有线程都必须获得同一对象上的锁,否则将无法实现同步。
看一看代码的这一部分:
if ( counter++ == 1 ) //confused in here.
o = new Object();
这部分根本不需要使代码线程安全。删除上面的代码,这会造成混乱。您已经在声明对象时创建了对象的实例。现在,为了确保所有线程之间的线程安全,让它们获得您已经创建的相同对象的锁。
看这里:static final Object o = new Object();
只是使对象成为最终对象,,以确保您不会错误地/有意地在代码中的任何其他地方分配新值。您可以直接以同步方式使用此对象,以确保线程安全。
发布于 2013-08-14 08:57:34
这是否意味着第一个线程将与第三个线程共享锁?
是的,此外,由于:
static int counter = 0
变量++
每个线程都有自己的变量counter
副本。这意味着以下条件永远不会是true
if ( counter++ == 1 )
o = new Object();
这就是为什么所有这些线程都将在声明o
时初始化的对象o
上共享相同的锁。
https://stackoverflow.com/questions/18225283
复制相似问题