有一个变量(seqJ)需要由线程更新两次。当两个线程需要更新变量时如何锁定或同步变量?
有这一个线程执行的这个变量,也就是两个动作:
都被执行的方法
IncrementAndGet(seqJ)
更新(seqJ)按照这里提到的确切顺序。
第二个线程在更新方法被调用后应该能够调用IncrementAndGet。我试图在这些方法中使用同步(锁定),但我推理说,一旦线程释放其中一个方法的锁定,那么另一个线程就可以通过其他方法访问seqJ,这会给我带来虚假的结果。
如何解决此问题?
MainClass{ public int incrementSeqJ() { return seqJ.incrementAndGet(); } public int getSeqJ() { return seqJ.get(); } public void updateSeqJ(int seqJ) { if (this.seqJ.get() < seqJ) this.seqJ.set(seqJ); } }
线程我在哪里使用这些方法:
public void run() { try { //socks.setSoTimeout(500); totalOrder = gma.totalOrder; ObjectInputStream ois = new ObjectInputStream(socks.getInputStream()); //Get reading stream ObjectOutputStream sendSSN = new ObjectOutputStream(socks.getOutputStream()); int i = 0; while (i < 2) { recObj = ois.readObject(); //Determine the type of message object received and do actions according to toString values. Use Switch cases. switch (Integer.parseInt(recObj.toString())) { //Receive MessageObject and send SuggestedSequenceNumber object to sending AVD case 1: { MessageObject mo = (MessageObject) recObj; updateUI = mo; int seqJ; /*if(mo.processNum == Integer.parseInt(gma.portStr)) seqJ = gma.getSeqJ(); else*/ seqJ = gma.incrementSeqJ(); mo.status = false; mo.sSN = seqJ; mo.sSNProcNum = Integer.parseInt(gma.portStr); Log.d(ReceiverTask.class.getSimpleName(), "Case 1 Adding"); totalOrder.addQ(mo); Object msg = new SuggestedSequenceNumber(mo.mID, seqJ, mo.processNum, mo.sSNProcNum); sendSSN.writeObject(msg); break; } case 3: { FinalMessage fm = (FinalMessage) recObj; MessageObject mo = totalOrder.findInQ(fm.mID, fm.processNum); if (mo == null) throw new NoSuchElementException(); else { mo.sSN = fm.sSN; mo.sSNProcNum = fm.sSNProcNum; mo.status = true; } gma.updateSeqJ(fm.sSN); Log.d(ReceiverTask.class.getSimpleName(), "Case 2 Adding"); totalOrder.addQ(mo); totalOrder.makeDeliverable(gma.getContentResolver()); gma.runOnUiThread( new Runnable() { public void run() { publishProgress(gma, ReceiverTask.this.updateUI); } }); ois.close(); sendSSN.close(); socks.close(); break; } } i++; } }catch(SocketTimeoutException ste){ Log.d(ReceiverTask.class.getSimpleName(), "Socket Timed Out"); } catch(ClassNotFoundException cnfe){ Log.d(ReceiverTask.class.getSimpleName(), "MessageObject not found"); } catch(IOException e){ Log.d(ReceiverTask.class.getSimpleName(), e.toString()); } }
}
假设线程1是incrementSeqJ方法:它增加值并将它放回SeqJ。现在在代码的第二部分中,必须在thread1调用updateSeqJ方法之后,thread2才能访问incrementSeqJ方法。
也许[''AtomicInteger''](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html)会解决你的问题吗? – NikolayKondratyev 2015-03-08 17:12:05
请添加您的代码,您最后一段中的“错误”对我来说并不清楚。 – Smutje 2015-03-08 17:12:36
@Smutje添加了代码。 – MessyCoder 2015-03-08 22:05:31