同步保护不适用于双线程

时间:2013-05-21 21:34:31

标签: java multithreading thread-safety synchronized

下面是我的精简版java代码供审阅。我有几个子类,当调用execParallel()时,会启动一个新线程。该线程和默认线程必须通过actionFunction()多次执行criticalFunction(),但是如果一次仅由一个进程执行,则此函数仅对给定的SubClassC连接正常工作。

我使用了关键字“synchronized”来防止并发执行,但实际上,criticalFunction()实际上是由两个线程同时调用的。

知道我做错了什么吗?

public class MainClass extends GlobalLibrary {
    public static SubClassA masterObj;

    public MainClass() {
        masterObj = new SubClassA();
    }        
    public static class SubClassA {
        public SubClassB subObj1;
        public SubClassB subObj2;        
        public SubClassA() {
            subObj1 = new SubClassB();
            subObj2 = new SubClassB();
        }
    }
    public static class SubClassB {
        public SubClassC conObj;        
        public Thread ut = null;        
        public SubClassB() {
            conObj = new SubClassC();
        }
    }
    public static class SubClassC {
        public TCPMasterConnection con=null;
        public SubClassC() {
            con = new TCPMasterConnection();
        }        
        public synchronized Object criticalFunction(int arg) {
            return otherClass.executeCritical(con, arg);
        }
    }    
    public boolean actionFunction(SubClassB subObj, int arg) {
        return (subObj.conObj.criticalFunction(arg)==null);
    }

    public class ActionThread implements Runnable {
        public SubClassB subObj;
        private int icode;
        public ActionThread(SubClassB arg1, int arg2) {
            subObj = arg1;
            icode = arg2;
        }
        public void run() {
            for (int i=0; i<10; i++) actionFunction(subObj, icode);
        }
    }    
    public void execParallel() {
        masterObj.subObj1.ut = new Thread(new ActionThread(masterObj.subObj1, 1));
        masterObj.subObj1.ut.start();

        actionFunction(masterObj.subObj1, 2);
        actionFunction(masterObj.subObj1, 3);
        actionFunction(masterObj.subObj1, 4);
        actionFunction(masterObj.subObj1, 5);
        actionFunction(masterObj.subObj1, 6);
    }
}

3 个答案:

答案 0 :(得分:1)

如果您的目标是保护otherClass.executeCritical(con, arg)调用,那么您需要锁定otherClass实例的粒度。如果目标是在给定时间只有一个线程使用“主连接”,这似乎是您非常想要的,那么您需要锁定粒度在TCPMasterConnection的实例。在后一种情况下,您的代码将如下所示:

    public Object criticalFunction(int arg) {
        synchronized(con) {
          return otherClass.executeCritical(con, arg);
        }
    }

现在,如果在otherClasscon(TCPMasterConnection)中都有多线程不安全的代码,那么您可能希望锁定具有更大的粒度。在这种情况下,一个简单的事情可能是锁定在类级别,如其他答案所述。

答案 1 :(得分:0)

是否要部分代码要进行同步,请改为:

Object lock = new Object();
public void doSomething{
   synchronized(lock){
    //your code
    }
}

Synchronized methods仅适用于实例级

答案 2 :(得分:0)

您在不同的实例上调用criticalFunction(),因此它们使用不同的锁。您需要在所有实例之间共享锁定。

试试这个

public Object criticalFunction(int arg) {
    synchronized (SubClassC.class) {
        return otherClass.executeCritical(con, arg);
    }
}