我是一名新手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();
}
}
答案 0 :(得分:2)
当你达到向上计数时,如果你做了典型的检查然后行动。这里的问题是几个线程可以同时到达这里。这意味着他们将拥有counter
的本地副本。不同的线程可能都有0个本地副本 - 这意味着它们将最多计数1并创建新对象 - 所有这些都是。但它们存储在一个静态容器中 - 它们可能有也可能没有本地副本。简而言之,这里发生的任何事情都是偶然的。它们最终可能会在同一个对象上进行同步 - 但它们可能会尝试在不同的对象上进行同步,这意味着它们根本不会同步。
您应该查看final
和volatile
个关键字。
final
表示某个引用在某处指向后无法重新指定。锁是一个好主意。如果您将声明更改为
final static Object o = new Object();
保证o
无法更改,并且所有同步都将在同一对象上。
volatile
表示禁止VM存储变量的线程局部副本。所有读写操作必须是内存。这意味着所有线程都将看到其他线程执行的写操作。
答案 1 :(得分:1)
为了确保多个线程之间正确的同步,所有人必须获取对同一对象的锁定,否则将无法实现同步。
看一下代码的这一部分:
if ( counter++ == 1 ) //confused in here.
o = new Object();
这部分根本不需要使代码线程安全。删除导致混淆的上述代码。您在声明对象时已经创建了该对象的实例。现在要确保所有线程之间的线程安全,让它们获取已经创建的同一对象的锁定。
看这里:static final Object o = new Object();
只需将对象设为最终,以确保您不会错误/有意地在代码中的任何其他位置分配新值。您可以以同步方式直接使用此对象以确保线程安全。
答案 2 :(得分:0)
这是否意味着第一个进入的线程将与之共享锁定 第三个?
是的,此外,由于:
static int counter = 0
变量++
每个线程都有自己的变量counter
副本。这意味着以下条件永远不会true
:
if ( counter++ == 1 )
o = new Object();
这就是为什么所有这些线程将在声明o
时初始化的对象o
上共享同一个锁。