假设我有一个被两个或更多线程访问的方法,我想让它成为线程安全的。
public int getVal(int x, int y, MyClass myObj)
{
int z;
z = getInt(myObj);
return x + y + z;
}在这种情况下,我认为我们不需要对x+y进行同步,因为它们是原语。
让我们假设getInt(myObj)修改了myObj的状态,这会影响z的值。
因此,我将不得不为行z = getInt(myObj);提供同步,但仅当两个线程在'myObj‘引用中传递相同的实例时。作为应用编程接口的编码器,我不知道这两个线程是否会为“myObj”传递相同的实例。在某些情况下,这些线程可能会在“myObj”引用中传递相同的MyClass实例,而在其他情况下,它们可能会在“myObj”引用中传递不同的MyClass实例。
那么,如何确保z = getInt(myObj)行的线程安全呢?(当然,我们不希望在传递的实例不同时进行同步,而只需要在传递的实例相同时进行同步。I很明显,这是无法确定的)。
假设MyClass不能成为不可变的,我认为以下可能是一个解决方案。
synchronized(myObj)
{
z = getInt(myObj);
}这是一个正确的解决方案吗?还有,我们还可以用什么其他方式来确保线程的安全性
z = getInt(myObj); (but only in case of different instances)?发布于 2011-03-10 03:31:42
你所拥有的是正确的。当你锁定一个对象时,它锁定的是那个实例,而不是那个类。( synchronize on a object )因此,如果我将一个对象的相同*实例*传递给两个不同的方法,它将正确地锁定该对象。但是,如果我传递两个不同实例,就不会有任何锁定,因为这两个实例都有自己的锁。
发布于 2011-03-10 03:32:56
如果getInt不修改this的状态,那么该方法是线程安全的。myObj对象的线程安全性取决于它的类: MyClass或持有它的对象的可响应性。并不是所有的方法都有责任,这些方法可能会把它作为一个参数。
您的解决方案(synchronized(myObj))是正确的:如果两个线程使用相同的myObj,两个线程将无法并发执行getInt方法。如果两个myObjs不同,它们将并发执行。
发布于 2011-03-10 04:45:56
synchronized(myObj) { z = getInt(myObj); } 将会做你想做的事情,但是在参数上同步会产生许多其他问题。例如,某个其他线程可能已经在该对象上同步(例如,可能该对象有一个正在被调用的同步方法),您可能会遇到死锁情况。
应该像封装其他任何东西一样封装同步。最好的解决方案是将getInt方法添加到MyClass中,并在该方法中的某个私有成员上进行同步。这样别人就不会弄乱你用来实现同步化的东西了。
例如:
public class MyClass {
private Object lockObject = new Object();
public int getInt() {
synchronized(lockObject) {
// do your thing
}
}
}请看这里:Avoid synchronized(this) in Java?引用了封装同步的重要性。
https://stackoverflow.com/questions/5251024
复制相似问题