如果有一个正在锁定对象的同步块,比如StringBuilder sb,哪一个线程正在执行这个同步块,其中sb被锁定,假设有另一个线程正在调用另一个尝试更改的方法那么sb的值(不在同步块中)是否允许这样做?
public static void main(String[] args) {
A a = new A();
new Thread(new MyRunnable(a), "T1").start();
new Thread(new MyRunnable(a), "T2").start();
}
static class MyRunnable implements Runnable {
A a;
public MyRunnable(A a) {
super();
this.a = a;
}
@Override
public void run() {
while (true) {
if ("T1".equals(Thread.currentThread().getName())) {
a.m1();
} else {
a.m2();
}
}
}
}
static class A {
StringBuilder abc = new StringBuilder("fdfd");
public void m1() {
synchronized (abc)
{
System.out.println("abc locked : " + abc);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();}
System.out.println("abc released: " + abc);
}
}
public void m2() {
System.out
.println(Thread.currentThread().getName() + " running");
System.out.println("trying to access abc");
abc.append("A");
System.out.println("abc accessed");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
}
我认为锁定对象不允许更改该对象以及修改或访问该对象。但是,从输出我看到锁定的对象可以修改:
输出:
abc locked : fdfd
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc released: fdfdAA
abc accessed
abc locked : fdfdAAA
T2 running
我没有得到这个,有人可以解释一下。锁定物体有什么用?这只是因为wait / notify / notifyAll方法吗?
答案 0 :(得分:2)
是的,是的。我想你需要阅读如果有一个正在锁定对象的同步块,比如StringBuilder sb,哪一个线程正在执行这个同步块,其中sb被锁定,假设有另一个线程正在调用另一个尝试更改的方法那么sb的值(不在同步块中)是否允许这样做?
synchronized
的内容。请参阅Java tutorial。它没有"锁定"限制其他线程对其进行操作的对象。它的作用是为锁定相同对象实例的线程的包围代码块提供互斥锁。对象中的字段完全能够在synchronized
块内部或外部进行变异。
在常量对象上进行同步总是一个好主意,所以我倾向于做类似的事情:
private final Object lock = new Object();
...
synchronized (lock) {
// only one thread allowed inside this block at a time
}
如果多个线程正在访问某种线程不安全的对象,我将在该对象上进行同步并对synchronized
块内的对象执行操作:
private final SomeUnsafeObject someObject = ...;
...
synchronized (someObject) {
// only one thread allowed inside this block at a time
someObject.someUnsafeMethodCall(...);
}
// no accesses (read or write) outside of the synchronized block
我认为锁定对象不允许更改该对象以及修改或访问该对象。但是,从输出我看到锁定的对象可以修改:
不,没有隐式阻止正在更改的对象。如果您只访问synchronized
块中内的对象字段,那么您就可以完成所需的操作。
public void m2() {
...
abc.append("A");
是的,因为你不在这里的synchronized (abc)
块内,所以没有任何东西阻止线程调用abc.append(...)
。
我没有得到这个,有人可以解释一下。锁定物体有什么用?这只是因为wait / notify / notifyAll方法吗?
同步允许您根据锁定对象(或该对象上的监视器)来控制对一个线程的代码块的访问。它还允许您执行lock.wait(...)
和lock.notify(...)
来控制线程操作并阻止/释放它们。
同步还会设置内存障碍,以便线程在进入synchronized
块时会看到存储在中央内存中的更改,并且当它离开时会看到它写入中央内存的更改。如果没有这些内存障碍,如果其他线程在没有同步的情况下访问StringBuilder
,那么它们可能看起来是该类的部分更新部分,可能导致NPE或其他故障。
答案 1 :(得分:0)
如果该锁由另一个线程持有,则线程只需等待访问锁定的代码区域。但是,如果它不需要锁定,它就不必等待,即,如果每个访问都被StringBuilder
块锁定,则synchronized
实例只是安全的。同样的锁。
在您的情况下,由于方法abc
中对m2()
的访问不在同步块中,因此线程不需要锁定,因此可以访问它。
答案 2 :(得分:0)
当您在Lock object
上进行同步时,所有线程都必须可以访问锁定对象,因此请使用属于调用代码的static object
或field
。
然后,您的代码将只能使用一个线程一次访问某些代码块。它不会阻止你以任何方式在你的代码中行事,但只有一个线程可以同时执行。