I was trying to create a few scenarios to demonstrate visibility issues while sharing variable across threads. And I noticed that in almost all the cases I tested, if inside run() I added a System.out.println() statement in the same block of code where I am using the shared variable, the visibility issue is not producible. I will provide one example:
Configuration details - Oracle Java6 64bit, Eclipse Juno SR 2
1)WITH VISIBILITY ISSUE:
public class NoVisibility_Demonstration extends Thread {
boolean keepRunning = true;
public static void main(String[] args) throws InterruptedException {
NoVisibility_Demonstration t = new NoVisibility_Demonstration();
t.start();
Thread.sleep(1000);
t.keepRunning = false;
System.out.println("keepRunning is false");
}
public void run() {
int x = 1;
while (keepRunning)
{
//System.out.println("If you uncomment this line, the code will work without the visibility issue");
x++;
}
System.out.println("x:"+x);
}
}
OUTPUT: The thread keeps running infinitely
2) WITHOUT VISIBILITY ISSUE:
THE SAME CODE AS ABOVE, WITH THE UNCOMMENTED println() STATEMENT IN THE run()
OUTPUT:
...
If you uncomment this line, the code will work without the visibility issue
If you uncomment this line, the code will work without the visibility issue
If you uncomment this line, the code will work without the visibility issue
x:19391
keepRunning is false
Since I noticed similar behavior in all the examples I tried, I am wondering if there is any data integrity check by JVM before any I/O operation.
PrintWriter is synchronized
public void println(String x) {
synchronized(this) {
this.print(x);
this.newLine();
}
}
Two sequential calls of System.out.println() in main thread and in second thread create a synchronization order between two threads. That means that all actions (in your case it is variable update), that happened in main thread before releasing a monitor (exiting synchronized method) will be seen by the code, executed in second thread after it acquires a monitor (enter synchronized method).
In simple words, yes, calling System.out.println() makes this synchronization.
This behaviour is implementation specific. In OpenJDK, println's body is synchronized altough the API does not state that it is.
Related
My program is based on two threads that share a protocol object. Depending on a boolean in the shared protocol object I try to make the other thread wait before using the protocol.
Main:
GameProtocol protocol = new GameProtocol();
MyThreadedClass thread1 = new MyThreadedClass(protocol);
MyThreadedClass thread2 = new MyThreadedClass(protocol);
thread1.start()
thread2.start()
Thread class:
GameProtocol protocol;
private MyThreadedClass(GameProtocol protocol){
this.protocol = protocol
}
private GamePackage waitCheck(GamePackage gp){
if(!gp.isWaiting()) {
return protocol.update(gp);
}
while(protocol.waitForCategory) {
//System.out.println(protocol.waitForCategory);
}
return protocol.update(gp);
}
Protocol class:
boolean waitForCategory = false;
public synchronized GamePackage update(GamePackage gp){
if(gp.myTurnToPickCategory){
gp.setWaiting(false);
waitForCategory = true;
} else {
gp.setWaiting(true);
waitForCategory = false;
}
return gp;
}
Now my intention is to make one thread wait untill the other thread have used the update method a second time. But the second thread get stuck in the while loop even tho the boolean waitForCategory have been set to false. Once I added the line System.out.println(protocol.waitForCategory); however it just started to work, and if I remove it it stops working again. I can't seem to understand how a ´sout´ on the boolean make it work. If anyone understands this would it be possible to solve it in another way? as having a sout inside a loop like that will make it messy.
As others have already explained, the introduction of println() inserts synchronization into the picture, so your code gives the illusion that it works.
In order to solve this problem you have to make sure everything is properly synchronized. In other words, gp.isWaiting() must also be synchronized, and protocol.waitForCategory must be moved into a method and synchronized.
Alternatively, quit trying to work with synchronization and use asynchronous message passing via java.util.concurrent.BlockingQueue instead. Your code will perform better, you will not be running the danger of race conditions, and your code will also be testable. (Whereas with synchronization your code will never be testable, because there is no test that will catch a race condition.)
While working on IntelliJ , I am unable to check that if the thread is holding the lock or not.
On eclipse GUI there is a lock like icon against the thread , telling us that it is holding that lock.
In below code snapshot, my thread is at notifyElementAdded() and holding the lock however, in a thread stack there is no such Icon or intimation from Intellij
So my question is how to check the same on IntelliJ GUI.
There is actually a boolean attribute to the Thread class in Java - Thread.holdsLock().
To get the name of the thread which holds the monitor you can use the code example below:
public static long getMonitorOwner(Object obj)
{
if (Thread.holdsLock(obj))
{
return Thread.currentThread().getId();
}
}
I don't think there is a similar functionality. But you can still check by getting the dump
You can click on Get Thread Dump in Debug window and then you can see the locked in the log to see that the thread is actually holding the lock
Create a custom variable in the Intellij debugging console using the plus button as shown in the image below.
Now every time you run the code in the debug mode, this variable will be re-calculated at your all debug points.
I created a variable- Thread.holdsLock(AwsS3ClientHelper.class) since I was acquiring a lock on the class itself. You can write any variable of your choice there. In your particular case, it will be Thread.holdsLock(observers).
This can be a potential feature request for IntelliJ to include this to their GUI product.
Programmatically, to verify this you can use the java.lang.Thread.holdsLock() method which returns true if and only if the current thread holds the monitor lock on the specified object
public static boolean holdsLock(Object obj)
Below snippet of run method for reference,
public void run() {
/* returns true if thread holds monitor lock */
// returns false
System.out.println("Holds Lock = " + Thread.holdsLock(this));
synchronized (this) {
// returns true
System.out.println("Holds Lock = " + Thread.holdsLock(this));
}
}
This is the first time I've encountered something like below.
Multiple Threads (Inner classes implementing Runnable) sharing a Data Structure (instance variable of the upper class).
Working: took classes from Eclipse project's bin folder, ran on a Unix machine.
NOT WORKING: directly compiled the src on Unix machine and used those class files. Code compiles and then runs with no errors/warnings, but one thread is not able to access shared resource properly.
PROBLEM: One thread adds elements to the above common DS. Second thread does the following...
while(true){
if(myArrayList.size() > 0){
//do stuff
}
}
The Log shows that the size is updated in Thread 1.
For some mystic reason, the workflow is not enetering if() ...
Same exact code runs perfectly if I directly paste the class files from Eclipse's bin folder.
I apologize if I missed anything obvious.
Code:
ArrayList<CSRequest> newCSRequests = new ArrayList<CSRequest>();
//Thread 1
private class ListeningSocketThread implements Runnable {
ServerSocket listeningSocket;
public void run() {
try {
LogUtil.log("Initiating...");
init(); // creates socket
processIncomongMessages();
listeningSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void processIncomongMessages() throws IOException {
while (true) {
try {
processMessage(listeningSocket.accept());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private void processMessage(Socket s) throws IOException, ClassNotFoundException {
// read message
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Object message = ois.readObject();
LogUtil.log("adding...: before size: " + newCSRequests.size());
synchronized (newCSRequests) {
newCSRequests.add((CSRequest) message);
}
LogUtil.log("adding...: after size: " + newCSRequests.size()); // YES, THE SIZE IS UPDATED TO > 0
//closing....
}
........
}
//Thread 2
private class CSRequestResponder implements Runnable {
public void run() {
LogUtil.log("Initiating..."); // REACHES..
while (true) {
// LogUtil.log("inside while..."); // IF NOT COMMENTED, FLOODS THE CONSOLE WITH THIS MSG...
if (newCSRequests.size() > 0) { // DOES NOT PASS
LogUtil.log("inside if size > 0..."); // NEVER REACHES....
try {
handleNewCSRequests();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
....
}
UPDATE
Solution was to add synchronized(myArrayList) before I check the size in the Thread 2.
To access a shared structure in a multi-threaded environment, you should use implicit or explicit locking to ensure safe publication and access among threads.
Using the code above, it should look like this:
while(true){
synchronized (myArrayList) {
if(myArrayList.size() > 0){
//do stuff
}
}
//sleep(...) // outside the lock!
}
Note: This pattern looks much like a producer-consumer and is better implemented using a queue. LinkedBlockingQueue is a good option for that and provides built-in concurrency control capabilities. It's a good structure for safe publishing of data among threads.
Using a concurrent data structure lets you get rid of the synchronized block:
Queue queue = new LinkedBlockingQueue(...)
...
while(true){
Data data = queue.take(); // this will wait until there's data in the queue
doStuff(data);
}
Every time you modify a given shared variable inside a parallel region (a region with multiple threads running in parallel) you must ensure mutual exclusion. You can guarantee mutual exclusion in Java by using synchronized or locks, normally you use locks when you want a finer grain synchronization.
If the program only performance reads on a given shared variable there is no need for synchronized/lock the accesses to this variable.
Since you are new in this subject I recommend you this tutorial
If I got this right.. There are at least 2 threads that work with the same, shared, datastructure. The array you mentioned.. One thread adds values to the array and the second thread "does stuff" if the size of the array > 0.
There is a chance that the thread scheduler ran the second thread (that checks if the collection is > 0), before the first thread got a chance to run and add a value.
Running the classes from bin or recompiling them has nothing to do. If you were to run the application over again from the bin directory, you might seen the issue again. How many times did you ran the app?
It might not reproduce consistently but at one point you might see the issue again.
You could access the datastruce in a serial fashion, allowing only one thread at a time to access the array. Still that does not guarantee that the first thread will run and only then the second one will check if the size > 0.
Depending on what you need to accomplish, there might be better / other ways to achieve that. Not necessarily using a array to coordinate the threads..
Check the return of
newCSRequests.add((CSRequest) message);
I am guessing its possible that it didn't get added for some reason. If it was a HashSet or similar, it could have been because the hashcode for multiple objects return the same value. What is the equals implementation of the message object?
You could also use
List list = Collections.synchronizedList(new ArrayList(...));
to ensure the arraylist is always synchronised correctly.
HTH
I am writing a blackberry app that communicates with a simple Bluetooth peripheral using text based AT commands - similar to a modem... I can only get it working on the blackberry using an event listener. So the communication is now asynchronous.
However, since it is a simple device and I need to control concurrent access, I would prefer to just have a blocking call.
I have the following code which tries to convert the communications to blocking by using a wait/notify. But when I run it, notifyResults never runs until getStringValue completes. i.e. it will always timeout no matter what the delay.
The btCon object runs on a separate thread already.
I'm sure I am missing something obvious with threading. Could someone kindly point it out?
Thanks
I should also add the the notifyAll blows up with an IllegalMonitorStateException.
I previously tried it with a simple boolean flag and a wait loop. But the same problem existed. notifyResult never runs until after getStringValue completes.
public class BTCommand implements ResultListener{
String cmd;
private BluetoothClient btCon;
private String result;
public BTCommand (String cmd){
this.cmd=cmd;
btCon = BluetoothClient.getInstance();
btCon.addListener(this);
System.out.println("[BTCL] BTCommand init");
}
public String getStringValue(){
result = "TIMEOUT";
btCon.sendCommand(cmd);
System.out.println("[BTCL] BTCommand getStringValue sent and waiting");
synchronized (result){
try {
result.wait(5000);
} catch (InterruptedException e) {
System.out.println("[BTCL] BTCommand getStringValue interrupted");
}
}//sync
System.out.println("[BTCL] BTCommand getStringValue result="+result);
return result;
}
public void notifyResults(String cmd) {
if(cmd.equalsIgnoreCase(this.cmd)){
synchronized(result){
result = btCon.getHash(cmd);
System.out.println("[BTCL] BTCommand resultReady: "+cmd+"="+result);
result.notifyAll();
}//sync
}
}
}
Since both notifyResults and getStringValue have synchronized clauses on the same object, assuming getStringValues gets to the synchronized section first notifyResults will block at the start of the synchronized clause until getStringValues exits the synchronized area. If I understand, this is the behaviour you're seeing.
Nicholas' advice is probably good, but you may not find any of those implementations in BlackBerry APIs you're using. You may want to have a look at the produce-consumer pattern.
It may be more appropriate to use a Latch, Semaphore, or a Barrier, as recommended by Brian Goetz book Java Concurrency in Practice.
These classes will make it easier to write blocking methods, and will likely help to prevent bugs, especially if you are unfamiliar with wait() and notifyAll(). (I am not suggesting that YOU are unfamiliar, it is just a note for others...)
The code will work ok. If you will use final object instead of string variable. I'm surprised that you don't get NPE or IMSE.
Create field:
private final Object resultLock = new Object();
Change all synchronized sections to use it instead of string field result.
I don't like magic number 5 sec. I hope you treat null result as timeout in your application.
This is gonna be a big mess to explain, but if anyone has any pointer, Please share!
From an applet I'm calling a 3rd parity lib which uses JNI do fetch some info in an OS specific manner. I don't know what it calls since I don't have the code and support isn't very responsive.
The thing is, all works well on windows (not just my machine) but on Mac OS one of the lib's methods throws a lib specific exception (a code and a "Cannot complete" ~message). It seems to be a security related issue since the method works when I call it from within init().
The jar with my applet is self-signed, the library has 4 more jars that are signed by the vendor. The lib's method is called from within an "AccessController.doPrivileged" block as an applet method that is called from JavaScript - and this all works, but on windows only.
On Mac this call from JavaScript to the applet method that calls the lib's method gets the exception.
Here is what I tried:
I moved the lib's method call in init() just for the test and it works ok, only without an "AccessController.doPrivileged" block.
I tried starting a Thread in init() (in start() as well):
- using a timer to have the Thread calls the lib's method every 10sec works fine and I can get the updated reply troughs a String buffer - this isn't a preferred solution.
- but if I use a flag in the thread so that the applet method can return the result it throws the same exception.
Here is the code in my applet's method:
checkRunner.refreshWindowsList = true;
while (checkRunner.refreshWindowsList) {
try {
Thread.sleep(300);
} catch (Exception ex) {
System.out.println("Ignoring exception: " + ex.getMessage());
}
}
return checkRunner.windowsTitles;
and in the Thread's run method:
try {
while (true) {
if (refreshWindowsList) {
windowsTitles = getWindowsTitlesPrivileged();
//windowsTitles = getWindowsTitles();
refreshWindowsList = false;
}
Thread.sleep(300);
}
} catch (Exception ex) {
System.out.println("Ignoring exception: " + ex.getMessage());
}
I don't understand how just passing a flag can cause the different results.
Furthermore, it seems that when the applet is created from JavaScript code all of it is sandboxed and the lib's method throws the exception even from init() ... again only on Mac OS.
If anyone made it this far - Thank You : )
To answer my question, even thought I highly doubt this is a common problem...
It turns out that the issue is not security related after all. The problem originates because of a quite inexplicable (to me) behaviour of the 3rd parity library - whenever the problematic method is called, even in a separate thread, and in the main thread their is a loop to wait for the answer - the exception is thrown.
So the following code fails, but when the sleep line at the end is removed it works ok. This happens no matter where the code is, init() or a method called from JavaScript - the behaviour is the same.
new Thread(new Runnable() {
public void run() {
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
callTheMehod();
}
});
}
}).start();
try { Thread.sleep(5000); } catch (exce....) {}
I ended up splitting the code into two methods called from JavaScript - one that calls the library method, putting the result in a volatile String and another that simply returns this volatile String. In JavaScript their is a waiting loop between the two. Strange thing is that if this loop has an interval that is very short - and the method to check for the result is called too often the library method fails again.
So it seems whenever there is too much load on the main thread the exception is thrown. This is quite inexplicable to me but since the library is using JNI I guess is a lot that could go wrong.