I am having a code this way,
public int handle_refresh(Data mmsg) throws Exception {
String custId = mmsg.getCustomerId();
CustomerThread t = custMap.get(mmsg.getCustomerId());
if (t == null || !t.isAlive()) {
t = (CustomerThread) context.getBean("custT");
t.initThread(mmsg.getCustomerId(), mmsg.getCustomerId(), mmsg.getMessageBody());
custSMap.put(mmsg.getCustomerId(), t);
t.createBufferThread();
t.start();
t.initStreaming();
}
synchronized (t) {
if (null != t) {
ret = t.addSymbols(mmsg);
}
}
return ret;
}
}
Here CustomerThread is checked in custMap,
Map custMap= new CustomerThread ();
if thread is there in custMap
1) then read spring appilcation context and get it. t = (CustomerThread) context.getBean("custT");
2) In initThread method set the name of the thread uniquely for each customer. t.initThread(mmsg.getCustomerId(), mmsg.getCustomerId(), mmsg.getMessageBody());
3) then put the newly created thread in to map custMap. custSMap.put(mmsg.getCustomerId(), t);
4) then in createBufferThread data is setting into cache.. t.createBufferThread();
5) then start the thread newly and then get data from db. t.start();
6) set the db connections
if thread is not there in custMap
1) synchronized (t) .
2) call t.addSymbols() method.
My questions are...
1) Here does the first if block executes only first time and if once thread is created always synchronized (t) is executed?
I mean all the above 1 to 6 steps in if block are executed only once?
2) then what does synchronized (t) does?
It looks to me that sychronized (t) is protecting the addSymbols method to make it thread-safe. Calls to this method are adding symbols, I assume, to some data structure within the t thread. It may be that other methods in that thread are synchronized which would mean that it would be locking on the Thread instance. That's what sychronized (t) is doing here.
But this is an extremely ugly way of adding thread-safety. The addSymbols(...) method should itself lock on a lock object or, if necessary, be a synchronized method. A class should be responsible for it's own locking and not require the caller to do something.
Couple other comments about your code:
t = (CustomerThread) context.getBean("custT");
The above code seems to be getting a thread instance from Spring. This is typically a singleton unless the "custT" bean is some sort of thread-factory. If it is not a factory bean then you are going to be getting the same thread-object for each call to your handle_refresh method and reinitializing it. This is most likely not what you want.
synchronized (t) {
if (null != t) {
ret = t.addSymbols(mmsg);
}
}
If t was null then the synchronized line would throw a NPE. You don't need the null check inside of synchronized.
CustomerThread t = custMap.get(mmsg.getCustomerId());
If the handle_refresh(...) method is called from multiple threads then you need to make sure that the custMap is properly synchronized as well.
The if block should only execute once per customer ID. Notice this line of code in the if block:
custSMap.put(mmsg.getCustomerId(), t);
It populates the map, so the next time a search is done with that customerId, it will be found and the synchronized block will be executed.
The Synchronized block will call a method on t inside a mutex lock.
Related
public class MyClass {
private List<Integer> resources = new ArrayList<>();
public synchronized Integer getAndRemoveResourceOrWait(Integer requestedResource) throws InterruptedException {
while(resources.stream().anyMatch((r) -> { return r >= requestedResource; })) {
wait();
}
Integer found = resources.stream().findFirst((r) -> {
return r >= requestedResource;
}).get();
resources.remove(found);
return found;
}
public void addResource(Integer resource) {
resources.add(resource);
notifyAll();
}
}
Thread "A" episodically invokes addResource with random value.
A few another threads actively invokes getAndRemoveResourceOrWait.
What I need to do to let method getAndRemoveResourceOrWait work concurrently?
For example, thread "X" invokes getAndRemoveResourceOrWait with variable 128 which does not exists in resources collection. So, it become waiting for it. While it is waiting, thread "Y" invokes getAndRemoveResourceOrWait with variable 64 and it exists in resources collection. Thread "Y" should not wait for thread "X" to complete.
What I need to do to let method getAndRemoveResourceOrWait work concurrently?
It simply needs to run on a different thread to the one that calls addResource(resource).
Note that getAndRemoveResource is a blocking (synchronous) operation in the sense that the thread making the call is blocked until it gets the answer. However one thread that is calling getAndRemoveResource does not block another thread calling getAndRemoveResource. The key is that the wait() call releases the mutex, and then reacquires it when the mutex is notified. What will happen here is that a notifyAll will cause all waiting threads to way up, one at a time.
However, there is a bug on your addResource method. The method needs to be declared as synchronized. If you don't call notifyAll() while the current thread holds the mutex for on this, you will get an exception. (And this is also necessary to ensure that the updates to the shared resources object are visible ... in both directions.)
Also, this implementation is not going to scale well:
Each waiting thread will scan the entire resource list on every update; i.e. on every call to addResource.
When a waiting thread finds a resource, it will scan the list twice more to remove it.
All of this is done while holding the mutex on the shared MyClass instance ... which blocks addResource as well.
UPDATE - Assuming that the Resource values are unique, a better solution would be to use replace ArrayList with TreeSet. This should work:
public class MyClass {
private TreetSet<Integer> resources = new TreeSet<>();
public synchronized Integer getAndRemoveResourceOrWait(
Integer resource) throws InterruptedException {
while (true) {
Integer found = resources.tailSet(resource, true).pollFirst();
if (found != null) {
return found;
}
wait();
}
}
public synchronized void addResource(Integer resource) {
resources.add(resource);
notifyAll();
}
}
(I also tried ConcurrentSkipListSet but I couldn't figure out a way to avoid using a mutex while adding and removing. If you were trying to remove an equal resource, it could be done ...)
My problem is a little complicated:
I have a concurrent map, the threads want to visit and update the map, if two thread want to fetch the same entry of the map, one should first get the map, update it, and the other should wait until the entry has been updated successfully and then fetch the entry.
My original thought is that: I can use another concurrent map, same key with the targeting map and use a latch as its value.
My code is like:
private final ConcurrentMap<Long, List<RowKeyMap>> targetmap;
private final ConcurrentMap<Long, CountDownLatch> helpermap;
long keyMillis; //key
CountDownLatch restoreLatch = helpermap.get(keyMillis);
if (restoreLatch != null) {
try {
restoreLatch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted trying to get " + keyMillis);
}
}
List<RowKeyMap> restoredata = targetmap.get(keyMillis);
if (restoredata == null) {
//find the entry should be restored, put a latch into the helpermap and restore it
restoreLatch = new CountDownLatch(1);
CountDownLatch existingLatch = helpermap.putIfAbsent(keyMillis, restoreLatch);
if (existingLatch == null) {
microshards = new ArrayList<>(count);
for (int i = 0; i < count; ++i) {
microshards.add(new RowKeyMap(some parameters));
}
List<RowKeyMap> existing = targetmap.putIfAbsent(keyMillis, microshards);
if (existing == null) {
{do actual restore job here}
} else {
microshards = existing;
}
restoreLatch.countDown();
restoresByDate.remove(keyMillis);
} else {
// Lost the race, wait for the restore task is complete and get the new restoredata
try {
existingLatch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted trying to get " + keyMillis);
}
{get the new restoredata}
}
}
But the current version has a bug:
Thread A executes through first line, gets null for restoreLatch
Thread B wakes up and executes through first line, also gets null for
restoreLatch
Thread B continues on to following lines, sees existingLatch is null
Thread B continues, puts a created-but-not-yet-restored-into list
into restoredata
Thread A wakes up and executes through, get the
created-but-not-yet-restored-into list from restoredata
Anyone has any ideas to solve this? Thanks!
So what you want is a lock per each map entry. I'm not sure a CountDownLatch is ideal here, because it cannot be re-used, and creating a new one each time complicates your problem.
But your basic problem is that you are not preventing the race condition for the lock itself.
In order to do that, you must first ensure that a lock object for the entry exists, and that if two threads go to the same entry, they will get the same lock.
You can do this by first creating a lock object, then use putIfAbsent to put it in the lock map:
Object entryLock = new Object();
Object returnedLock = helpermap.putIfAbsent( keyMillis, entryLock );
entryLock = returnedLock == null ? entryLock : returnedLock;
What this does is ensure that any two threads that are trying to access the same entry (keyMillis) will get the same lock instance. If thread A is the first to run the putIfAbsent line, then the new object it created in the first line is going to be the one to be placed in the helper map, and it's going to get null back, which means it will also use the object it just placed in the map - entryLock. Thread B then comes along and create its own entryLock. But when it tries the putIfAbsent line, there is already an object mapped to keyMillis, returnedLock, and that's the object it will use (in this case, the original new lock it created will be discarded to the garbage collection).
So whichever order thy get to the putIfAbsent line, they will be using the same lock instance. Now the next step is:
Lock the lock.
Run your processing of the data in the targetMap, creating it if it doesn't exist, updating it if it does, etc. All this time, other threads for this particular keyMillis are waiting, but threads with other keyMillis don't.
Unlock the lock. One of the other threads that wait for this keyMillis entry will now lock the lock.
To do this is pretty simple:
synchronized(entryLock) {
// All operations on the particular entry
}
If you need fancier lock facilities then use ReentrantLock or a CyclicBarrier. A CountDownLatch will need to be replaced with a new one to be usable, and that would defeat the arrangement above, which pretty much relies on the lock object being the same for all threads.
My problem is a little complicated...
Uh oh, I've got bad news for you. If you think that problem is complicated.... You actually have identified the simplest problem in multi-threaded program. It's called mutual exclusion.
You can do it like this in Java:
final Object lock = new Object();
synchronized (lock) {
// some protected statements
}
synchronized (lock) {
// some more protected statements
}
The JVM guarantees that no more than one thread can be in a synchronized(foo) block for the same object foo at the same time.
use the synchronized either at the method declaration or inside a block of code.
see here : https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Use objects that implement the Lock interface. Java has several of these objects by default that you can use. Here is a tutorial that explains what locks are and how to use them.
I have done some research and could not find a solution to this problem.
From this topic Synchronization, When to or not to use? i understand i could use synchronized, but doing so doesn't solve the problem.
The case is that i have a method in which a Thread is used to create an ArrayList. In that same Thread another method is called after a BufferedReader has finished reading a file and the lines are being added to the first List.
In the second method the first list is being used to create the second List. When all that is done, the first method uses the second list.
This is somewhat the code i use, if there is something not clear please ask and i will try to provide the info needed.
public synchronized void theBaseList() {
Thread t = new Thread() {
#override
public void run() {
try(
while((line = br.readLine()) != null) {
firstList.add(line):
}
}
nextMethod();
currentObject = (Object[]) secondList.get(0); // throws an exception
}
}
};
t.start();
public synchronized void nextMethod() {
Thread t1 = new Thread(){
double objectListSize = calculateObjectListLength(firstList.size());
#override
public void run() {
try {
// create Objects
secondList.add(objects);
}
}
};
t1.start();
}
When i use a Thread in nextMethod() to create a new list of Objects from the items in the first list, i get an ArrayIndexOutOfBoundsException saying
Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
I avoided this by not using a Thread in the second method and all works fine.
If i do use 2 Threads and make both methods synchronized, it still throws the exception.
Is it possible or should i just settle by not using a Thread in the second method? I thought synchronized was for dealing with this sort of problems. I don't understand why it doesn't work.
Let's say your methods are defined in a class named Sample and you've created an instance mySample. This appears to be what your code is doing:
main thread calls mySample.theBaseList() and synchronizes by locking on mySample.
theBaseList() defines thread1 and starts it.
theBaseList() exits scope, thus unlocking on mySample.
thread1 reads in the lines of a file and adds them to list1 (these operations are not synchronized)
thread1 calls mySample.nextMethod()
mySample.nextMethod() synchronizes by locking on mySample
nextMethod() defines thread2 and starts it.
nextMethod() exits scope, thus unlocking on mySample.
* thread2 sets up list2 (these operations are not synchronized)
* thread1, having returned from nextMethod() reads from list2 (these operations are not synchronized)
The last two operations are the cause of your race condition.
In your case, using synchronized methods is perhaps too coarse grained. A better option may be to synchronize on the object on which both threads operate, secondList.
nextMethod();
synchronized(secondList) {
currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}
synchronized(secondList) {
// create Objects
secondList.add(objects);
}
EDIT:
synchronized(secondList) {
nextMethod();
secondList.wait();
currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}
synchronized(secondList) {
// create Objects
secondList.add(objects);
secondList.notifyAll();
}
When I use the code shown below, IntelliJ IDEA tell me "expression expected" in the code DecibelSample. What is that mean, How can I fix it?
if (mDecibelSample == null) {
synchronized (DecibelSample) { // expression expected
if (mDecibelSample == null) {
mDecibelSample = new DecibelSample();
}
}
}
Assuming that DecibelSample is a class, this is not valid Java code.
Modify your code like this in order to get rid of the compile error:
synchronized (DecibelSample.class) {}
Your code won't work because synchronized needs some instance to lock against. In the modified example above it will use the Class instance.
You could also change it to synchronized (this) {} in which case it would use the instance of the class your method is in as the lock.
Third option is to define arbitrary object to use as a lock, for instance like this:
private static final Object LOCK = new Object();
...
public void foo() {
synchronized(LOCK) {}
}
This would probably be the best approach, since locking against the current instance or class instance has some disadvantages. See this SO answer for more details:
More information about the synchronized keyword can be found in Java Language Specification.
The synchronized keyword requires an Object. DecibelSample is a classname, not an Object.
The Object will be used to ensure synchronization : i.e. when a thread need to execute the code inside the synchronized block : the thread must acquire a lock on the Object.
if the lock can be aquired by the thread then the code inside the block is executed and the lock is released so that another thread can acquire it.
if the lock cannot be acquired : the thread wait until the lock (owned by another thread) is released.
In your case, you need an Object to support the locking mechanism:
//used for locking only
// don't consume useless memory : a zero-sized array is fine
// ensure that the LOCK is shared between all threads : let's make it static
// ensure that the object used for locking cannot be changed by anyone : let's make it final
// at first sight : we don't need to synchronize on this Object in another class : keep it private.
private static final Object[] LOCK = new Object[0];
...
if (mDecibelSample == null) {
synchronized (LOCK) {
if (mDecibelSample == null) {
mDecibelSample = new DecibelSample();
}
}
}
I have one thread1:
if(object != null){
object.play();
}
and another thread2 that can write null into object reference at any time.
I will run these threads at same time. I know thread2 can rewrite object reference after the null check and that will throw NullPointerException. Is it possible for thread2 to rewrite object reference after NullPointerException check?
Is it possible to for thread2 to rewrite object reference after NullPointerException check ?
Absolutely - it could change the value of object while the play() method is executing, if that's what you mean. That wouldn't cause an error in itself.
Note that without synchronization or other memory barriers, thread2 could change the value of object without thread1 noticing for an indeterminate period of time.
It's hard to say what you ought to do, without any other knowledge of the bigger aim of the code.
Simple synchronized example:
/**
To maintain thread safety, only access this through getter and setter
or other synchronized method
**/
private ObjectType object;
public synchronized void setObject(ObjectType object) {
this.object = object;
}
public synchronized ObjectType getObject() {
return object;
}
public void doPlay() {
final ObjectType obj = getObject();
//here, thread 2 can change "object", but it's not going to affect this thread
//as we already safely got our reference to "object" in "obj".
if(obj != null){
obj.play();
}
}
public synchronized void alterativeDoPlay() {
//the difference here is that another thread won't be able to change "object"
//until the object's play() method has completed.
//depending on the code in play, this has potential for deadlocks, where as
//the other `doPlay` has zero deadlock potential.
if(object != null){
object.play();
}
}
If object is an instance variable or a static variable that can be changed from multiple threads, its value can change between the time you test it in the if statement and the time when you call its instance method.
You can modify the code to avoid this problem by copying the object into a local variable, like this:
Playable objectCopy = object;
if(objectCopy != null) {
objectCopy.play();
}
Since objectCopy is a local variable, its value cannot change between the test and the call of play. Of course the state of the playable object itself can change, but that is not something that can be fixed by null checking.
You can use CountDownLatch here. Where Thread1 will wait to count down by Thread2 and you can perform the task in thread2 and stop count down.
Code snippet -
CountDownLatch latch = new CountDownLatch(1);
new Thread1(latch).start();
new Thread2(latch).start();
public class Thread1 extends Thread {
private final CountDownLatch startLatch;
public Thread1(CountDownLatch startLatch) {
this.startLatch = startLatch;
}
public void run() {
try {
startLatch.await();
// ... perform task
} catch (InterruptedException iex) {}
}
}
public class Thread1 extends Thread {
private final CountDownLatch stopLatch;
public Thread1(CountDownLatch stopLatch) {
this.stopLatch = stopLatch;
}
public void run() {
try {
// perform task
} finally {
stopLatch.countDown();
}
}
}
According to Brian's Law :
When we write a variable, which next has to be read by another thread, or when we are reading a variable which has lately been written by another thread, then use synchronization.
Synchronize the atomic statements or getter/setters which has access to the crucial state of data with the same monitor lock.
- Use synchronization.
- You can use CountDownLatch from java.util.concurrent
You will need to use some form of synchronisation primitive to solve this problem. See "Syncrhonised Statements" here. In your case you will need to wrap the whole if block and any places in any threads that use or update object2.
As my professor said: "Concurrency is a pretty unstable guy. We never know what to expect of him." Comming to your question:
Is it possible for thread2 to rewrite object reference after
NullPointerException check?
Yes
Thread2 can access the object many times during 1 occurrence of thread1. Or the other way around. There may be many occurrences of thread1, while thread2 accesses the object.
If you use simple
System.out.println();
in many places in your code, you may notice the output in the console to be displayed AFTER the NullPointerException error(if it wasn't caught).