请考虑以下代码。
import static java.lang.System.out;
public class Task
{
public Integer k = new Integer(10) ;
public Task()
{
out.println(k + " constructor of Task : " + Thread.currentThread().getName());
}
}
import static java.lang.System.out;
public class Executor2 implements Runnable
{
private Task task;
public Executor2(Task t)
{
out.println("constructor of Executor2 : " + Thread.currentThread().getName());
task = t;
}
@Override
public void run()
{
synchronized(task.k)
{
task.k = 88;
out.println("changed value of task.k to : " + task.k + " " + Thread.currentThread().getName());
try
{
out.println("sleeping");
Thread.sleep(5000);
}
catch (InterruptedException ex)
{
ex.printStackTrace(out);
}
out.println("done");
}
}
}
import static java.lang.System.out;
public class Executor3 implements Runnable
{
private Task task;
public Executor3(Task t)
{
out.println("constructor of Executor3 : " + Thread.currentThread().getName());
task = t;
}
@Override
public void run()
{
synchronized(task.k)
{
task.k = 888;
out.println("changed value of task.k to : " + task.k + " " + Thread.currentThread().getName());
}
}
}
------------------------------------------------------------
public class Main
{
public static void main(String[] args)
{
Task task = new Task();
Executor2 executor2 = new Executor2(task);
Thread thread2 = new Thread(executor2);
thread2.start();
Executor3 executor3 = new Executor3(task);
Thread thread3 = new Thread(executor3);
thread3.start();
}
}
以下是该计划的输出。
任务的10个构造函数:main
Executor2的构造函数:main
Executor3的构造函数:main
将task.k的值更改为:88 Thread-0
睡觉
将task.k的值更改为:888 Thread-1
完成
令人惊讶的是输出行:将task.k的值更改为:888 Thread-1 ,预计不会在输出行之前打印:完成。 为什么在睡眠持续时间过去之前释放对Integer对象的锁定?
感谢。
答案 0 :(得分:2)
synchronized(task.k)
{
task.k = 888;
更改同步的对象会破坏同步点。然后,当您仍然在旧对象上进行同步时,尝试打印新对象。不要替换正在同步的对象线程!
答案 1 :(得分:1)
扩展大卫施瓦茨所说的话:几乎在所有情况下,如果你要写这个:
synchronized (foo) {
...
}
然后引用锁定对象的变量应该是final
字段:
class MyClass {
final Object foo = new Object();
...
void someMethod(...) {
synchronized (foo) {
...
}
}
...
}
这将阻止你将来犯同样的错误。
答案 2 :(得分:0)
同意上述内容。同样在使用私有锁时,一个缺陷就是不能锁定字符串文字 - 字符串文字是共享资源。
private final String lock = “xx”;
private final String lock = new String(“xxx”);
第二次锁定很好。