Concurrent readers-writers behaving in an unexpected way - java

I am trying to make a program that runs several parallel readers and writers. I start some threads in a loop using ExecutorService class, the run() method of the Writer class just call two methods StartWrite()and EndWrite() and for the Reader class, StartRead() and EndRead(). These methods are wrapped in a monitor.
Here's the monitor:
public class RWMonitorAN {
static int readers = 0;
static boolean writing = false;
public static RandomAccessFile f;
public static int n = 0;
private final ReentrantLock mylock = new ReentrantLock();
private final Condition toWrite = mylock.newCondition();
private final Condition toRead = mylock.newCondition();
public RWMonitorAN()
{
try { f = new RandomAccessFile("datos.dat", "rw"); } catch (IOException e) {}
}
void StartRead() {
mylock.lock();
try
{
if (writing)
try {
toRead.wait();
toWrite.wait();
} catch (InterruptedException e) {}
readers++;
try
{
f.seek(0);
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
System.out.println();
} catch (IOException e) { e.printStackTrace(); }
}
finally { mylock.unlock(); }
}
void EndRead() {
mylock.lock();
try
{
readers--;
if (readers == 0)
toWrite.signal();
}
finally { mylock.unlock(); }
}
void StartWrite() {
mylock.lock();
try
{
if (writing || readers != 0)
try {
toWrite.wait();
} catch (InterruptedException e) {}
writing = true;
try
{
f.writeInt(n);
} catch(IOException e) {}
n++;
}
finally { mylock.unlock(); }
}
void EndWrite() {
mylock.lock();
try
{
writing = false;
toWrite.signal();
toRead.signal();
}
finally { mylock.unlock(); }
}
But there's a problem: the program ends before the expected number of data is written and read. For example, if I start 20 writer and 20 reader threads, I expect 20 numbers to be written and read, but only 10~ are. If I run the program again (datos.dat would be already created) it keeps writing and reading and then 20 numbers are written.
Test:
1st run
Written in the last executed thread: 0 1 2 3 4
Read in the last executed thread: 0 1 2 3 4
2nd run
Written in the last executed thread: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Read in the last executed thread: 0 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
What's wrong? How can I make it work properly?
EDIT: I tried printing the number of readers every time a reader finishes reading and the same number of readers is being printed several times. Shouldn't this not be happening? readers-- is executed in a lock protected section of the code.

You are catching your exceptions everywhere and not reporting them anywhere nor do anything else to serve them. The first thing to "make it work properly" would probably be to check if there are exceptions called. For example, if you use more than one iterators on one data structure in Java it will probably throw concurrentModificationException at the start, to prevent unexpected behaviour in the future.
What is the point of using multiple readers from a file if, as it appears, you set every new one to the very beginning of a file with seek(0)? And your reader appears to try to read the whole file
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
and your writer tries to read a single int in
f.writeInt(n);
so if you started n threads I would not expect n numbers to be read.
Finally, have you considered what happens when you start another writer/reader after startRead unlocked mylock but before EndRead locked it again? Why not to put the logic from EndRead just at the end of startRead method then?

Related

How thread sleep works internally in java? [duplicate]

This question already has answers here:
How Thread.sleep() works internally
(5 answers)
Closed 3 years ago.
It may be a dumb question but i have researched it alot and i am not getting any satisfactory knowledge.
Can anyone help me to understand?
my code
public class sleepclass extends Thread {
public static void main(String[] args) {
sleepclass t1 = new sleepclass();
sleepclass t2 = new sleepclass();
t1.start();
t2.start();
}
public void run() {
for (int i = 1; i < 5; i++) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println(i);
}
}
}
Output :
1
1
2
2
3
3
4
4
Now as per the output i can see both thread gone to a sleep state. and both comes after at the same time
My question is :
1 . Since sleep is a static method how both works and sleep at same time? (explain in layman please).
Can i sleep only t1 and left t2 to run?
Thread.sleep() sleeps the current thread. It has no effect elsewhere.
If you want one thread to sleep and one not in your current code, you would have to have some kind of indicator to control it. Such as a boolean flag which you would then check:
if(shouldSleep) {
Thread.sleep(5000);
}
Otherwise all threads will execute the same code, and all threads will sleep for 5 seconds.

System.out.println with java volatile

I have an example like that:
public class MainApp {
private volatile static int MY_INT = 0;
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
static class Thread1 extends Thread {
#Override
public void run() {
while(true) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
static class Thread2 extends Thread{
#Override
public void run() {
while(true) {
MY_INT++;
System.out.println("2 : " + MY_INT);
}
}
}
}
And the output is:
1 : 1
2 : 2
1 : 3
2 : 4
1 : 5
1 : 7
1 : 8
1 : 9
1 : 10
2 : 6
1 : 11
1 : 13
I don't understand why after printing 1:10 and the next line is 2:6. Can anyone explain the result? Thanks in advance
There are several issues here:
threads may not run in parallel. They run in time slices (default: 15.6 ms on a PC; 64 ticks per second, see timer resolution (Microsoft)). This is why you don't see 1:x and 2:x one after another, but several 1:x after each other.
using volatile does not help with synchronization. You need real synchronization objects such as AtomicInteger or the synchronized keyword. Therefore you may see skipped numbers (not the case in your output, but it may occur). You need the synchronization around both, the ++ and the println() if you want to see unique numbers
Console output is buffered and synchronized, because you don't want 2 println statements to mix the output on one line
The PrintStream in System.out and the volatile field MY_INT are independently synchronized, so the following can happen:
Thread 1 Thread 2
read MY_INT = 4
write MY_INT = 5
read MY_INT = 5
read MY_INT = 5
write MY_INT = 6
read MY_INT = 6
println 5
read MY_INT = 6
write MY_INT = 7
read MY_INT = 7
println 7
...
println 6
That is, because the volatile field and the PrintStream returned by System.out are independently synchronized, printing may occur in non-ascending order.
The following could also happen:
Thread 1 Thread 2
read MY_INT = 1
read MY_INT = 1
write MY_INT = 2
write MY_INT = 2
read MY_INT = 2
println 2
read MY_INT = 2
println 2
because ++MY_INT is actually compiled into a read, a computation, and a write. Since volatile reads and writes are separate synchronization actions, other threads may act in between, and mess the counter up.
If you want ascending numbers being printed by separate threads, the easiest way is:
void run() {
while (true) {
synchronized (lock) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
where lock is an object shared by all threads accessing MY_INT.

Program not always terminating? [duplicate]

This question already has answers here:
Why is i++ not atomic?
(10 answers)
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I wanted to test out multithreading for a project of mine, trying to also develop a solution in case something goes wrong.
So I made this small test:
main
public class main
{
static int addToCounter;
static int addToErrorCounter;
public static void main(String[] args) throws InterruptedException
{
int threads = 10;
Executor exec = new Executor();
for (int i = 0; i < threads; i++)
{
double error = Math.random();
testClass aldo = new testClass();
Thread thread = aldo.getThread(300, error);
exec.execute(thread);
}
while (threads != (addToCounter + addToErrorCounter))
{
System.out.println("Not all threads finished, number of finished threads is: " + (addToCounter + addToErrorCounter));
Thread.sleep(50);
}
System.out.println("Number of Threads that finished correctly: " + addToCounter);
}
}
testClass
import test1.main;
public class testClass
{
public Thread getThread(long time, double error)
{
Thread thread = new Thread()
{
public void run()
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (error > 0.5)
{
main.addToErrorCounter++;
throw new java.lang.Error("HELLO");
}
System.out.println("I DID THIS!");
main.addToCounter++;
}
};
return thread;
}
}
(you'll have to fix the imports, also I use a custom class Executor, although that's only a wrapper for ExecutorService)
The weird behaviour is that sometimes it works properly, and sometimes it doesn't (total terminated thread count is 9, although I can see clearly it printed "I DID THIS!" and the error exactly 10 times).
Any fix?
The Problem might be a racecondition.
the "++" operator is not atomic.
Imageine the following scenario. There are two Threads at the same time. both want to increase a number and finish.
The initial value of the number is 0.
Thread 0 reads the number, knows now it is 0.
Thread 1 reads the number, knows now it is 0.
Thread 0 (who knew it was 0) now writes 1 to the memory.
Thread 1 does not know, that the number has changed, and still believes the number is 0 so he also writes a 1 to the memory.
You need something like a synchronizing mechanisim, something like a lock, or a semaphore or something else.
have a look at this for more information: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
for your example you could use the "synchronized" example from that link.
add a method to your main class looking like this to increment the addToCounter and also to the addToErrorCounterto remove the effects from your error counter:
synchronized AddToError(int e){
addToError += e;
}
synchronized IncCounter(){
addToCounter++;
}
call those methods in your threads in the testclass instead of incrementing them unsynchronized.
My guess is that the postfix operator (main.addToCounter++) is not atomic. This line of code is probably equivalent to something like:
int temp = main.addToCounter;
main.addToCounter = temp + 1;
return temp;
With multiple threads doin this at the same time, two threads could obtain the same value for temp (because both peform the first line in the above pseudo-code before either performs the second), and hence the counter total will be too small once all threads are complete. See Why is i++ not atomic? for more information.
A quick fix in this situation is to make addToCounter an AtomicInteger, then use addToCounter.incrementAndGet() in place of addToCounter++.

Java thread wont synchronize

I just started working with notify, synchronized and wait, and it almost works, but only when I let the second Thread sleep() for 1 ms. You can see my console output at the end.
My main:
public static void main(String[] args) {
InfoPaket paket = new InfoPaket();
TestThread testThread = new TestThread(paket);
TestThread2 testThread2 = new TestThread2(paket);
}
My "Lock" Class
public class InfoPaket {
String info;
char infoDataSign;
boolean newInfo = false;
public synchronized boolean isNew(){
if (!newInfo){
try {
System.out.println("waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return newInfo;
}
public synchronized String getInfo() {
newInfo = false;
return info;
}
public synchronized void setInfo(String info) {this.info = info;
newInfo = true;
notify();
}
My two test Thread
1.
public class TestThread implements Runnable {
InfoPaket info;
int i = 0;
public TestThread(InfoPaket info) {
this.info = info;
new Thread(this,"TestThread").start();
}
public void run() {
while(true){
i++;
getInfo();
}
}
void getInfo(){
info.isNew();
System.out.println("he got it... " + info.getInfo() + " " + i);
}
2.
public class TestThread2 implements Runnable{
InfoPaket info;
Thread t;
int i = 0;
public TestThread2(InfoPaket info) {
this.info = info;
t = new Thread(this,"TestThread");
t.start();
}
public void run() {
while(i < 500000){
i++;
setInfo();
}
}
void setInfo(){
info.setInfo("lelaoao");
System.out.println("here " + i);
try {
t.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Here my results which are very clear and nice (except for the start):
waiting
he got it... lelaoao 1
waiting
here 1
here 2
he got it... lelaoao 2
waiting
here 3
he got it... lelaoao 3
waiting
here 4
he got it... lelaoao 4
waiting
here 5
he got it... lelaoao 5
waiting
here 6
he got it... lelaoao 6
And so on..
But putting the 2. thread everytime asleep slows down the program,
but without it I get something strange that I can't explain to myself:
waiting
here 1
he got it... lelaoao 1
he got it... lelaoao 2
waiting
here 2
here 3
he got it... lelaoao 3
he got it... lelaoao 4
waiting
here 4
here 5
here 6
here 7
here 8
here 9
here 10
he got it... lelaoao 5
he got it... lelaoao 6
waiting
You code is working as expected (as coded), except - 1) You have some bad code 2) You may have misunderstood the concept.
Let me first start by saying what your code is doing:
You have a InfoPaket which is shared among your 2 thread and hold info about packet, and keeps track whether new info is received or not.
Then your have TestThread which will check if new info is received or not, if new info is not recieved then it will wait and once new info is received then you will print the info (which is always "lelaoao") along with your loop counter, like this he got it... lelaoao 23
Then your have TestThread2 which will set the info and notify the waiting thread and then print the loop counter of this thread like this - "here " + i.
Now, most important thing for your understand is that thread scheduling is unexpected and depends on underlying OS thread scheduling mechanism as well as JVM implementation, so you cannot expect that if thread 2 has set info then then certainly thread 1 will execute, you can try to enforce it putting Thread.sleep(1) or Thread.yeild(), please note that Thread.yeild() is not portable and it is good that you are not using it and should not be use it, instead of it you should use Thread.sleep(1)
Now let come to bad code and some important concepts:
Bad code
The most wrong thing you were doing is you were starting a new thread from the constructor, don't ever try to start a new thread from the constructor because it will cause your reference to leak even before your constructor has completed. Read this excellent article.
You don't need a reference of current thread in TestThread2 because you can directly do Thread.sleep(1); which will cause current thread to sleep.
You were printing System.out.println("he got it... " + info + " " + i); and System.out.println("here " + i); from your main thread, however you should print these from synchronized block to ensure that there is no interleaving, because in absence of synchronization interleaving could occur and you could see he got it... lelaoao 3 before here 3 which is logically wrong.
Now, below is the fixed code which will consistent produce correct result (considering your are giving thread 1 chance to run once thread 2 has set info), output is also placed in the end.
InfoPaket.java
public class InfoPaket {
String info;
char infoDataSign;
boolean newInfo = false;
public synchronized boolean isNew() {
if (!newInfo) {
try {
System.out.println("waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return newInfo;
}
public synchronized void getInfo(int i) {
newInfo = false;
System.out.println("he got it... " + info + " " + i);
}
public synchronized void setInfo(String info, int i) {
this.info = info;
newInfo = true;
System.out.println("here " + i);
notify();
}
public static void main(String[] args) {
InfoPaket paket = new InfoPaket();
TestThread testThread = new TestThread(paket);
TestThread2 testThread2 = new TestThread2(paket);
new Thread(testThread, "testThread").start();
new Thread(testThread2, "testThread2").start();
}
}
TestThread.java
public class TestThread implements Runnable {
InfoPaket info;
int i = 0;
public TestThread(InfoPaket info) {
this.info = info;
}
public void run() {
while (true) {
i++;
getInfo(i);
}
}
void getInfo(int i2){
info.isNew();
info.getInfo(i2);
}
}
TestThread2.java
public class TestThread2 implements Runnable {
InfoPaket info;
int i = 0;
public TestThread2(InfoPaket info) {
this.info = info;
}
public void run() {
while (i < 500000) {
i++;
setInfo(i);
}
}
void setInfo(int i2) {
info.setInfo("lelaoao", i2);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output:
waiting
here 1
he got it... lelaoao 1
waiting
here 2
he got it... lelaoao 2
waiting
here 3
he got it... lelaoao 3
waiting
here 4
he got it... lelaoao 4
waiting
here 5
he got it... lelaoao 5
waiting
here 6
he got it... lelaoao 6
waiting
here 7
he got it... lelaoao 7
waiting
here 8
he got it... lelaoao 8
waiting
here 9
he got it... lelaoao 9
waiting
here 10
he got it... lelaoao 10
waiting
here 11
he got it... lelaoao 11
waiting
here 12
he got it... lelaoao 12
waiting
here 13
he got it... lelaoao 13
waiting
here 14
he got it... lelaoao 14
waiting
here 15
he got it... lelaoao 15
waiting
here 16
he got it... lelaoao 16
waiting
here 17
he got it... lelaoao 17
waiting
here 18
he got it... lelaoao 18
waiting
here 19
he got it... lelaoao 19
waiting
here 20
he got it... lelaoao 20
waiting
here 21
he got it... lelaoao 21
waiting
here 22
he got it... lelaoao 22
waiting
here 23
he got it... lelaoao 23
waiting
here 24
he got it... lelaoao 24
waiting
here 25
he got it... lelaoao 25
waiting
here 26
he got it... lelaoao 26
waiting
here 27
he got it... lelaoao 27
waiting
here 28
he got it... lelaoao 28
waiting
here 29
he got it... lelaoao 29
waiting
here 30
he got it... lelaoao 30
waiting
here 31
he got it... lelaoao 31
Important concepts to be clear about
I think you might be missing some concept so you are thinking output to be crazy.
Once you have set the info using thread 2 there is no guarantee that thread 1 will run because thread scheduling is unexpected and depends on underlying OS thread scheduling mechanism as well as JVM implementation, I have highlighted more point about this in the start with Thread.yield() and Thread.sleep(). With that note, if you don't use Thread.sleep(1) then you just can't expect output to be consistent, as I have shown below.
When you do Thread.sleep then it doesn't release the lock, if that thread is acquiring some lock.
Once you do notify(); then you can't expect the waiting thread to be "runnable" immediately and the thread which is acquiring the lock will not release immediately release the lock as soon as notify(); is called, lock will be released only once that synchronized block/method is finished.
If you don't do Thread.sleep(1) in your 2nd thread then you can't expect the consistent output, and reasons I have explained above.
OP's comment:
Do you know any a more efficent way of transmitting data from on
thread to an other one?
Either you have "shared memory" or "message passing"; shared memory is what we are doing in this case, and if you want to go for message passing then you can go for Java API like blocking queue (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html) implementation, but that's becomes all together different story.

Java wait for next print

I want the second print to happen after 2 seconds.
System.out.println("First print.");
//I want the code that makes the next System.out.println in 2 seconds.
System.out.println("This one comes after 2 seconds from the println.");
Just use Thread#sleep:
System.out.println("First print.");
Thread.sleep(2000);//2000ms = 2s
System.out.println("This one comes after 2 seconds from the println.");
Note that Thread.sleep can throw an InterruptedException, so you will need a throws clause or a try-catch, like:
System.out.println("First print.");
try{
Thread.sleep(2000);//2000ms = 2s
}catch(InterruptedException ex){
}
System.out.println("This one comes after 2 seconds from the println.");
or:
public void something() throws InterruptedException {
System.out.println("First print.");
Thread.sleep(2000);//2000ms = 2s
System.out.println("This one comes after 2 seconds from the println.");
}
try {
Thread.sleep(2000); //2 secs
catch (InterruptedException e) {
}
You should use Thread#sleep:
Causes the currently executing thread to sleep
Note that you should use try-catch block around the call to Thread.sleep() because another Thread could interrupt main() while it's sleeping. In this case, it's not necessary to catch it because there is only one Thread active, main().
try {
Thread.sleep(2000)
catch (InterruptedException e) {
System.out.println("main() Thread was interrupted while sleeping.");
}
Thread.currentThread().sleep(2000); //2000 milliseconds = 2 seconds
If you want your java code to sleep for 2 sec you can use the sleep function in Thread:
Thread.sleep(millisec);
The millisec argument is how many milliseconds you want to sleep f.ex:
1 sec = 1000 ms
2 sec = 2000 ms
and so on..
So your code will be something like this:
System.out.println("First print.");
try {
Thread.sleep(2000); //2 secs
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("This one comes after 2 seconds from the println.");
(the try-catch is needed because sometimes it will throw a excpetion if the SecurityManager dont allow the thread to sleep but dont worry, thats will never happen..)
-Max

Categories

Resources