Java:同步线程失败

时间:2016-08-10 08:13:47

标签: java multithreading thread-synchronization

我有以下代码:

for (int iThreadCounter = 1; iThreadCounter <= CONNECTIONS_NUM; iThreadCounter++){ 
  WorkThread wt = new WorkThread(iThreadCounter);
  new Thread(wt).start(); 
  m_arrWorkThreadsToCreate.add(wt); 
} 

这些线程调用以下代码:

int res = m_spLegJoin.call(m_workTread, m_workTread.getConfId());

这是LegJoinSp类中的调用方法:

public class LegJoinSp extends ConnEventSp {

    private static final int _LEG_JOIN_ACTION_CODE = 22;
    private static int m_nLegId = Integer.valueOf(IniUtils.getIniValue("General", "LEG_ID_START"));
    private final Lock m_lock = new ReentrantLock();

    public int call(WorkThread a_workThread, String a_sConfId) {

        synchronized (this) {

            //m_lock.lock();
            m_nLegId++;

            boolean bPass = false;

            Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId);

            if (super.call(a_workThread, a_sConfId, _LEG_JOIN_ACTION_CODE, "" + m_nLegId) == 0) {

                bPass = true;

            } else {
                bPass = false;
            }

            //m_lock.unlock();

            if (bPass) {

                Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId + " returned leg id " + m_nLegId);

                return m_nLegId;
            } else {

                return -1;
            }
        }

    }

    public Lock getLock() {
        return m_lock;
    }

}

我有2个线程调用此call()方法。 m_nLegId以100开头。 如你所见,我试图用两个方法锁定方法

synchronized(this)

m_lock.lock() and m_lock.unlock()

问题在于,当我第一次到达 if(bPass)内部代码时,它会将102写入我的日志作为m_nLegId值。但是我希望它是101,因为 m_nLegId ++; 语句。 似乎第二个线程在第一个线程执行的同步块结束之前设法进入代码。

我该如何解决?

谢谢

2 个答案:

答案 0 :(得分:2)

对我而言,您的错误与m_nLegIdstatic field并且您尝试同步当前实例而不是类的访问权限有关,因此您不能正确防止并发修改你的领域。

我的意思是

synchronized (this) {

应该是

synchronized (LegJoinSp.class) {

注意:如果您只需要一个计数器,请考虑为您的字段使用AtomicInteger而不是int。

答案 1 :(得分:1)

问题是您正在为每个线程创建一个新对象,但是您应用锁定的方式仅适用于同一个对象(因为您在上应用了锁定)。
因此,如果你想在类级别上应用锁定,那么你可以创建一个静态对象并对该对象应用锁定,这可以达到你想要达到的目的(如果我根据评论)