Java: 线程同步失败

Java: Fail in synchronizing threads

我有以下代码:

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里面的调用方法class:

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 值写入我的日志。但是,由于 m_nLegId++; 语句,我希望它是 101。 似乎第二个线程设法在第一个线程执行的同步块结束之前进入代码。

我该如何解决?

谢谢

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

对我来说,你的错误与 m_nLegId 是一个 static field 这一事实有关,你试图同步对当前实例的访问而不是 class 这样你就不会无法正确阻止您的字段的并发修改。

我是说

synchronized (this) {

应该是

synchronized (LegJoinSp.class) {

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