考虑下面我编写的用于测试非原始变量(myObject
)的锁定的类。如果所有线程都在SynchronizationTest
的同一对象实例上工作,那么我的问题是:
我理解如果thread1正在执行set(...)
方法,那么任何其他线程(比如说thread2)都可以执行anotherSetWithSynchronized(...)
或anotherSetWithoutSynchronized(...)
。
如果thread1在执行SynchronizationTest
时锁定了set(...)
的对象,是否意味着它已获取所有成员对象变量的锁定?就像在这种情况下myObject
。如果没有,
如果thread1正在执行set(...)
,那么thread2可以同时执行anotherSetWithSynchronized(...)
吗?
两个方法都不能同时由线程执行吗?
这个设计错了吗?我是否需要在myObject
synchronized
方法中明确锁定set(...)
。像这样:
public synchronized void set(MyValue myValue) {
synchronized (myObject) {
myObject.put(myValue);
}
}
这是我的代码:
public class SynchronizationTest {
private MyObject myObject = new MyObject();
public synchronized void set(MyValue myValue) {
myObject.put(myValue);
}
public void anotherSetWithSynchronized(MyValue myValue) {
synchronized (myObject) {
myObject.put(myValue);
}
}
public void anotherSetWithoutSynchronized(MyValue myValue) {
myObject.put(myValue);
}
}
答案 0 :(得分:6)
1:不,set(...)方法受“SynchronizationTest”对象锁定的保护。
2:是的,他们的防护对象与你设计的不同。
3:一个线程每次只能运行一个方法。如果你的意思是两个线程,正如我已经解释过的那样,这些方法由两个对象保护,因此它们可以同时执行
4:是的,你是对的。
Java中的内部锁定在“Java Concurrency In Practice”一书中描述如下:
同步块有两部分:对对象的引用 将作为锁,并由一个守卫的代码块 锁。同步方法是同步块的简写 跨越整个方法体,其锁是对象 该方法正在被调用。 (静态同步方法使用 锁的Class对象。)
有关更多详细信息,请参阅“实践中的Java并发”一节的第2.3.1节。
答案 1 :(得分:0)
对象上的线程锁定是否也确保锁定成员对象?
没有
据我所知,如果thread1正在执行set(...)方法,那么任何其他线程(比如说thread2)都可以执行另一个setWithSynchronized
是的,除非myObject与'this'具有相同的值。
答案 2 :(得分:0)
synchronized方法相当于
public void method(){
synchronized(this){
//something
}
}
1)没有
同步仅适用于指定的对象,而不适用于其成员。
2)没有
3)是的,他们不能,只有一个线程可以在由给定监视器保护的同步部分内激活
4)您不需要(如果使用显式同步,则不应在方法级别上使用synchronized)。但它更好(对于库/大型代码库),因为那时你可以控制谁可以访问发生同步的实例,所以其他人不能同步它并导致死锁。