-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding in concurrent logic to help prevent ConcurrentModificationException #89
base: transitclock-merge
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,7 @@ | |
import org.transitclock.utils.Time; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
/** | ||
* This is a very important high-level class. It takes the AVL data and | ||
|
@@ -1583,19 +1584,19 @@ public void cacheAvlReportWithoutProcessing(AvlReport avlReport) { | |
VehicleState vehicleState = | ||
VehicleStateManager.getInstance().getVehicleState( | ||
avlReport.getVehicleId()); | ||
|
||
ReentrantLock l = new ReentrantLock(); | ||
l.lock(); | ||
// Since modifying the VehicleState should synchronize in case another | ||
// thread simultaneously processes data for the same vehicle. This | ||
// would be extremely rare but need to be safe. | ||
synchronized (vehicleState) { | ||
// Update AVL report for cached VehicleState | ||
vehicleState.setAvlReport(avlReport); | ||
// Update AVL report for cached VehicleState | ||
vehicleState.setAvlReport(avlReport); | ||
|
||
// Let vehicle data cache know that the vehicle state was updated | ||
// so that new IPC vehicle data will be created and cached and | ||
// made available to the API. | ||
VehicleDataCache.getInstance().updateVehicle(vehicleState); | ||
} | ||
// Let vehicle data cache know that the vehicle state was updated | ||
// so that new IPC vehicle data will be created and cached and | ||
// made available to the API. | ||
VehicleDataCache.getInstance().updateVehicle(vehicleState); | ||
l.unlock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. again, if the updateVehicle(vehicleState) is at issue by being outside of the synchronized block, then consider moving it. |
||
} | ||
|
||
private boolean isCanceled(VehicleState vehicleState) { | ||
|
@@ -1637,7 +1638,7 @@ private void logInvalidAssignment(VehicleState vehicleState) { | |
* The new AVL report to be processed | ||
*/ | ||
public void processAvlReport(AvlReport avlReport) { | ||
IntervalTimer timer = new IntervalTimer(); | ||
IntervalTimer timer = new IntervalTimer(); | ||
|
||
// Handle special case where want to not use assignment from AVL | ||
// report, most likely because want to test automatic assignment | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
|
||
import java.io.Serializable; | ||
import java.util.Objects; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
import org.transitclock.applications.Core; | ||
import org.transitclock.db.structs.ArrivalDeparture; | ||
|
@@ -196,6 +197,8 @@ public boolean isEarlierStopPathThan(Indices indices) { | |
* @return The resulting Indices object | ||
*/ | ||
public Indices increment(long epochTime) { | ||
ReentrantLock l = new ReentrantLock(); | ||
l.lock(); | ||
++segmentIndex; | ||
if (segmentIndex >= block.numSegments(tripIndex, stopPathIndex)) { | ||
segmentIndex = 0; | ||
|
@@ -217,6 +220,7 @@ public Indices increment(long epochTime) { | |
} | ||
} | ||
} | ||
l.unlock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why a lock is needed here? |
||
|
||
return this; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
import java.util.Date; | ||
import java.util.HashMap; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
@@ -79,7 +80,8 @@ public void uncaughtException(Thread t, Throwable e) { | |
* @return | ||
*/ | ||
private static String threadNameWithCounter(String name) { | ||
synchronized (threadNameCountMap) { | ||
ReentrantLock l = new ReentrantLock(); | ||
l.lock(); | ||
Integer count = threadNameCountMap.get(name); | ||
if (count == null) { | ||
count = 1; | ||
|
@@ -88,16 +90,19 @@ private static String threadNameWithCounter(String name) { | |
count++; | ||
} | ||
threadNameCountMap.put(name, count); | ||
l.unlock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the threadNameCountMap.put is causing the issue, consider moving it inside the synchronized block. |
||
return name + "-" + count; | ||
} | ||
} | ||
|
||
@Override | ||
public void run() { | ||
logger.debug("Created NamedThread {}", getName()); | ||
ReentrantLock l = new ReentrantLock(); | ||
try { | ||
l.lock(); | ||
numAlive.incrementAndGet(); | ||
super.run(); | ||
|
||
} catch (Throwable t) { | ||
// Log the problem but do so within a try/catch in case it is | ||
// an OutOfMemoryError and need to exit even if get another | ||
|
@@ -141,6 +146,7 @@ public void run() { | |
System.exit(-1); | ||
} | ||
} finally { | ||
l.unlock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, you really need to convince me this is necessary. Locking an entire thread seems completely unreasonable. I suspect you don't understand how this thread is used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can remove this and retest. |
||
numAlive.decrementAndGet(); | ||
logger.debug("Exiting NamedThread {}", getName()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it the avlReports.put(...) is the problem here, I suggest extending the synchronized (avlReports) block instead. The Reentrant lock doesn't give you anything different as I understand it.