2016-08-10 9 views
1

I次のコードを持っている:Javaは:同期のスレッドで失敗

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; 
    } 

} 

私はこのcall()メソッドを呼び出す2つのスレッドを持っています。 あなたは、私は問題は(bPass)場合、私は最初のに到達したときということです

synchronized(this) 

m_lock.lock() and m_lock.unlock() 

の両方でメソッドをロックしようとしている見ることができるようにm_nLegIdが100 で開始されます内部コードは、m_nLegId値として102に自分のログに書き込みます。しかし、私はそれがm_nLegId ++のために101であることを期待しています。声明。 最初のスレッドの実行で同期ブロックが終了する前に、2番目のスレッドがコード内に入るようになっているようです。

どうすれば修正できますか?

は事は(あなたがこのにロックを適用して)あなたはすべてのスレッドで新しいオブジェクトを作成しているが、あなたはロックを適用する方法は、同じオブジェクトに適用されているあなたに

+1

主に 'LegJoinSp'クラスがどのように使われているのか、より多くのコードを含める必要があります。表示される動作の最も簡単な説明は、2つの異なるオブジェクトを使用していることです。プライベート・ロックを同期またはロックすることはできません。 – Kiskae

+0

@Kiskae私は両方の方法を使用していません。私はそれらを別々に試しました。 1回の同期と1回のロックオブジェクト。 – dushkin

+1

は、MCVE http:// stackoverflowルールに従ってスレッドを起動するコードを表示します。以下のためのCOM /ヘルプ/ MCVE –

答えて

2

私の場合は、m_nLegIdstatic fieldであり、クラスの代わりに現在のインスタンスのアクセスを同期しようとしているため、フィールドの同時変更を適切に防止できません。場合にはあなただけintの代わりに自分のフィールドにAtomicIntegerを使用することを検討して、カウンタが必要:

私が意味

synchronized (this) { 

はむしろ

synchronized (LegJoinSp.class) { 

NBであるべき。

+0

ビンゴ!ありがとうございました! – dushkin

1

ありがとうございます。
したがって、クラスレベルでロックを適用する場合は、静的オブジェクトを作成し、そのオブジェクトにロックを適用して達成することができます(コメントに基づいて問題を正しく理解した場合)

+0

zstringありがとうございます。あなたの答えはニコラスのものと非常に似ています。だから私はそれに投票しましたが、解決策として両方をマークすることはできません。 – dushkin