I have been assigned an exercise from my uni professor that goes as follow:
"A fence object is an object that has a collection of objects, and can wait on any of those objects is signaled. There is an add(Object) method, which adds an object to the collection. There is also an await() method: this allows to wait on any object of the collection to be signaled. Whenever the add(Object) method is called while the await() method is active, the argument of the add is put in queue. Write the source code using the following interface: ".
public interface Fence {
public void await() throws InterruptedException;
public void add(Object o);
}
So, only when the same number of notify() and objects in queue (aka the number of add(Object) ) are called, the await() terminates and the object in the queue are finally added to the collection. <- this is something I got wrong and realized after writing my code
I did make the implementation as follow:
import java.util.LinkedList;
public class FenceImpl2 implements Fence{
private LinkedList<Object> collection;
private Object mutex; ;
static boolean iswaiting = false;
public FenceImpl2() {
this.collection = new LinkedList<Object>();
this.mutex = new Object();
}
#Override
public void await() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
synchronized(mutex) {
mutex.wait();
iswaiting = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}}});
t1.start();
}
#Override
public void add(Object o) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized(mutex){
if(iswaiting == true) {
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
collection.add(o);
}
}}});
t2.start();
}
public Object getList() throws InterruptedException {
synchronized(mutex){
System.out.println("Collection list: \n");
for(Object o : collection) {
System.out.println(o);
Thread.sleep(1000);
}
System.out.println("------- \n");
return collection;
}
}
public void notification() {
Thread thread = new Thread(()->{
synchronized(mutex){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mutex.notify();
}
});
thread.start();
}
public static void main(String[] args) throws InterruptedException {
FenceImpl2 f = new FenceImpl2();
Object o1 = 1;
Object o2 = 2;
Object o3 = 3;
Object o4 = 70;
f.add(o1);
System.out.println("Add 1");
f.add(o2);
System.out.println("Add 2");
f.add(o3);
System.out.println("Add 3");
f.await();
System.out.println("Await active ");
f.add(o4);
System.out.println("Aggiungo 70 - Shouldn't appear. Forced in queue");
f.getList();
f.notification();
System.out.println("Notify() sent - 70 should now appear in the collection");
f.getList();
}
}
After submitting it to my professor I have been told two things:
The synchronization is not correct: the await "unlocks" after the first notify and that shouldn't happen because it doesn't wait for the other (if any) objects that are in queue to be notified.
^Let me say I know how to fix that easily but
Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
Here it finally comes my problem. How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
I tried removing the threads but obviously as soon as I'm calling mutex.wait() the program locks and the code right after that calls the notification method is not reached.
Why did my professor tell me using threads is wrong?
How can I use a wait() and then call a notify() in two separate methods without having the program lock?
Here's an example of what I mean:
public class testw {
private Object mutex;
boolean condition = false;
public testw() {
this.mutex = new Object();
}
public void startWait() {
synchronized(mutex) {
try {
Thread.sleep(1000);
condition = true;
while(condition == true) {
System.out.println("Waiting!");
mutex.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sendNotify() {
synchronized(mutex) {
try {
Thread.sleep(3000);
System.out.println("Notify!, not waiting anymore");
condition = false;
mutex.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
testw t = new testw();
t.startWait();
t.sendNotify();
}
Without using threads, when I startWait() is called the main thread goes in wait, but there's no way that sendNotify() to be called and the programs freezes. Is there a way to do this without using threads or am I missing something?
Thank you very much.
I have been told...Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
The whole point of a method named await() is that it should not return until the event that the caller wants to wait for has happened.
Your await() method doesn't wait. It creates a new thread and then it immediately returns. The new thread waits for something, but after that it just dies without doing anything useful. The new thread might as well not exist at all.
Your add(o) method doesn't make a whole lot of sense either. I'm not even sure what you were trying to do with it, but I think you need to take a step back, and try to explain to the duck why you thought that either of those two methods should create a new thread.
How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
The Oracle "Guarded Blocks" tutorial is an oldie but a goodie. If you work through it to the end, it should give you a pretty clear idea of how and why and when to use wait() and notify().
https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
Related
I try to restart thread but synchronized block in thread keep locked after restarted. I shouldn't change socket properties because some processes take too long but when network connection lost it hangs forever. I try to use InterruptedException but it doesn't work. Is there any way to release this lock?
public static void main(String[] args) {
try {
synchronizedBlock t1 = new synchronizedBlock();
t1.start();
Thread.sleep(500);
t1.cancel();
t1 = new synchronizedBlock();
t1.start();
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
}
}
public class synchronizedBlock extends Thread {
boolean isRunning = true;
boolean isRunning2 = true;
public static Object[] locks = new Object[5];
public synchronizedBlock() {
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
}
public void cancel() {
isRunning = false;
interrupt();
}
public void socketProces() {
while (isRunning2) {
}
}
public void proces(int index) {
try {
synchronized (locks[index]) {
System.out.println("Synchronized Block Begin");
socketProces();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
System.out.println("Run begin");
while (isRunning) {
proces(1);
}
Thread.sleep(1);
} catch (InterruptedException e) {
//Do Something
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result:
Run begin
Synchronized Block Begin
Run begin
When you start the synchronizedBlock thread you'll get a stack trace like this I think:
run -> proces -> socketProcess.
Then because isRunning2 = true, the thread will enter an infinite loop in socketProcess and never terminate.
Keep in mind that in Java there is no such thing as 'restarting' a thread. Once started, a thread can never be restarted. Indeed, you are creating two sycnchronizedBlock objects, not restarting a single object.
As a side note, it is generally problematic to overwrite static state in a class constructor, as you're doing with the locks variable, without synchronization.
The issue here is the Integer cache which is used in the for loop to initialize the synchronizedBlock.locks array:
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
When this code is run again, due to the constructor of the second synchronizedBlock, the synchronizedBlock.locks array contains the same Integer instances which where created when this for loop was executed for the first time. This means that the synchronized (locks[index]) lock will be on the same Integer object. As you have already one thread holding the lock for the Integer(1) object, the second thread waits outside the lock waiting for it to be released.
This is also problematic in combination with the fact that the first thread is not terminating. Your method
public void socketProces() {
while (isRunning2) {
}
}
is an endless loop as you don't change the value of isRunning2, ever. Also, the interrupt() method itself does not stop any thread. Instead, it sets just an internal flag in the Thread class, which can be checked with isInterrupted() and interrupted(). You have to check this flag and react on it like "Oh, someone wants me to stop, so I stop now".
To solve your problem you should at least quit your thread when the "isInterrupted" flag of the Thread instance is set. You can do it like this:
public void socketProces() {
while (isRunning2) {
if (Thread.interrupted()) {
return;
}
}
}
Instead of returning from socketProces() normally you could throw an InterruptedException like other methods do.
Also, depending on how you want to initialize/use the instances you want to lock on with synchronized(...), you might want to consider on how you create/fill the synchronizedBlock.locks array and which objects you want to use (the Integer cache might be problematic here). It depends on you if the creation of a new synchronizedBlock instance will/should/shouldn't create new objects to lock on in the synchronizedBlock.locks array.
Let's say I have below code
public class ContinueIfCannotLock implements Runnable
{
static List<LockingObject> lockObjects = new ArrayList();
#Override
public void run()
{
for(LockingObject obj : lockObjects)
{
synchronized ( obj )
{
// do things here
}
}
}
}
and the LockingObject is just and empty class. Also let's assume before these threads start we have 100 of objects in the LockingObject list.
So how can I let a thread to continue to next object in the list if it cannot acquire the lock to the current element. So that no thread (at least until all the objects are not locked by a thread) is waiting inside the loop.
Try using Thread.holdsLock(Object obj),
Returns true if and only if the current thread holds the monitor lock on the specified object.
~Thread (Java Platform SE 8)~
static List<LockingObject> lockObjects = new ArrayList();
#Override
public void run(){
for(LockingObject obj : lockObjects){
if(Thread.holdsLock(obj)){
continue; //continue the loop if object is locked.
}
synchronized(obj){
// do things here
}
}
}
}
You May use locks:
static List<ReentrantLock> lockObjects;
public static void init(){
lockObjects = new ArrayList<>(100);
for(int i = 0; i<100;i++){
lockObjects.add(new ReentrantLock());
}
}
#Override
public void run()
{
for(LockingObject lock : lockObjects)
{
if(lock.tryLock()){
try{
//dostuff
}finally{
lock.unlock();
}
// break if you only want the thread to work once
break;
}
}
}
If your only goal with this was to have a maximum of 100 threads working at the same time, you could also use a Semaphore which is a lock that let's multiple threads lock it up to a specified value.
I have three classes below. Main, two threads and Obj whose methods are synchronized
public class DeadLocks {
public static void main(String[] args) {
SyncObj so = new SyncObj();
ThreadObj to = new ThreadObj(so);
ThreadObj1 to1 = new ThreadObj1(so);
to.start();
to1.start();
}
}
class SyncObj {
synchronized void foo() {
System.out.println("Foo Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar();
}
synchronized void bar() {
System.out.println("bar started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
foo();
}
}
class ThreadObj1 extends Thread {
SyncObj so;
public ThreadObj1(SyncObj so) {
this.so = so;
}
#Override
public void run() {
so.bar();
}
}
class ThreadObj extends Thread {
SyncObj so;
public ThreadObj(SyncObj so) {
this.so = so;
}
#Override
public void run() {
so.foo();
}
}
In the above code I'm calling synchronized methods on the same object. Both the methods are executing and calling each other simultaneously.There is no deadlock situation. Could anyone explain why? sorry for such a silly question.
As far as I can see, you are using the same object (so) for both the cases. So there is no case for a deadlock. You would need to lock on two or more objects wherein each critical section requires the lock other than the one that it is holding. That other lock is held by "another" thread.
Confusing, this will enlighten: "https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html"
You would never ever deadlock in a scenario that you describe. In this scenario there is only one so that is being shared and is being synchronized with.
Let me give you an example to illustrate:
Suppose Andy and Sandy are playing with two soccer balls B1 and B2.
Now further suppose that both Andy and Sandy have balls B1 and B2 in their possession respectively. For example Andy has ball B1 and Sandy has ball B2.
Now they devise a game wherein they need both the balls each.
Now Sandy wants ball B1 as well and at the same time, Andy wants B2.
And both of them cannot relinquish the balls that they hold. Andy will not give up B1 and vice-versa.
So both of them cannot continue and are stuck. We call this a deadlocked situation.
Hope this example helps. You could use your imagination to increase the number of balls in play to 3 or 4 (and so on..) and / or increase the number of players.
You do not get a deadlock because your program does not meet two of the four necessary conditions of forming it:
mutual exclusion - yes,
hold on partial allocation - no,
no pre-emption - yes,
circular dependency - no
You need at least two resources, "A" and "B", to form a deadlock. One thread should grab "A" and attempt to grab "B", while the other should grab "B", and attempt to grab "A".
I'm not sure why you expect a deadlock here. It's true that only one of objects has an access to synchronized section, but then it has this access as much as it wants. You can modify the code to make it clear:
public class DeadLocks {
public static void main(String[] args) {
SyncObj so = new SyncObj();
ThreadObj to = new ThreadObj(so);
ThreadObj1 to1 = new ThreadObj1(so);
to.start();
to1.start();
}
}
class SyncObj {
synchronized void foo(String msg) {
System.out.println("Foo Started: " + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar(msg);
}
synchronized void bar(String msg) {
System.out.println("bar started: " + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
foo(msg);
}
}
class ThreadObj1 extends Thread {
SyncObj so;
public ThreadObj1(SyncObj so) {
this.so = so;
}
#Override
public void run() {
so.bar("TO1");
}
}
class ThreadObj extends Thread {
SyncObj so;
public ThreadObj(SyncObj so) {
this.so = so;
}
#Override
public void run() {
so.foo("TO");
}
}
You can see the following output:
Foo Started: TO
bar started: TO
Foo Started: TO
bar started: TO
Foo Started: TO
bar started: TO
You can consider 'synchronized' to mean lock(this), where 'this' is a SyncObj instance. Therefore there is exactly one lock, and it's impossible to obtain a deadlock.
While others have already pointed out that a deadlock only occurs when you have two resources where each thread locks one and then waits for the other, I think there is one crucial point missing, where your entire confusion probably comes from:
synchronize on a method does not create a lock for that particular method, it creates a lock for the entire object it belongs to. Thus your class is equivalent to this:
class SyncObj {
void foo() {
synchronized(this) {
System.out.println("Foo Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar();
}
}
void bar() {
synchronized(this) {
System.out.println("bar started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
foo();
}
}
}
Now it should be much more clear, why you don't get a deadlock.
You can easily modify your code to be prone to a deadlock by introducing two resources, one for each method:
class SyncObj {
private Object foolock = new Object();
private Object barlock = new Object();
void foo() {
synchronized(foolock) {
System.out.println("Foo Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar();
}
}
void bar() {
synchronized(barlock) {
System.out.println("bar started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
foo();
}
}
}
Deadlock is not possible using a single instance because no two threads of the same object can access more than one synchronised method.
In the above example if thread 1 is accessing foo method. Thread 2 cannot access either foo nor bar method. Untill thread 1 finishes it task
I would like to realize class in Java, which will be wait for new data from different threads and when he got it, this class will process it and again go to wait new data. I want to realize this using only synchronized, wait, notifyAll commands. I tried some variants:
1) using one thread, which wait by command lockObject.wait(). But when all active threads finish their work, this thread will be waiting forever. Of course, I can make method stopProcess(), but it is not safety, because another programmer can forget to call it.
2) using one daemon-thread, it will not work, because when all active threads finish their work, my daemon-thread die, but he can have some data which he must to process
3)when new data is coming - create new thread, which will process data. while thread is alive(he process given data), he will receive new data. when it is no data coming and all old data was processed, thread finish to work. Minus of this variant is - when data is coming through some period (when thread have time to process old data and die), a new thread will be created. I think it's bad for performance or/and memory. Am I right?
Is it possible to solve my problem using only one or two(may be using daemon and active thread in combination) threads and not using stopProcess() method??
Here some code
My realize of blocking queue
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
public void add(T el){
synchronized (queue){
queue.add(el);
}
}
public T getFirst(){
synchronized (queue){
return queue.poll();
}
}
public int getSize(){
synchronized (queue){
return queue.size();
}
}
}
Data class
public class Data {
//some data
public void process(){
//process this data
}
}
First variant of code
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread;
private Object lock = new Object();
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeUpToProcess();
}
}else{
throw new Exception("");
}
}
public synchronized void start() {
if (!run){
run = true;
processThread = new Thread(new Runnable() {
public void run() {
while (run || queue.getSize()!=0){
while(queue.getSize() == 0 && run){
//if stopProcess was not called
//and no active threads
//it will not die
waitForNewData();
}
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
}
});
processThread.start();
}
}
public synchronized void stopProcess() {
if (run){
run = false;
wakeUpToProcess();
}
}
private void waitForNewData(){
try{
synchronized (lock){
lock.wait();
}
}catch (InterruptedException ex){
ex.printStackTrace();
}
}
private void wakeUpToProcess(){
synchronized (lock){
lock.notifyAll();
}
}
}
In second variant I make processThread as daemon. But when active threads die, processThread finish to work, but there are some data in queue, which i have to process.
Third variant
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread = null;
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeExecutor();
}
}else{
throw new Exception("ProcessData is stopped!");
}
}
public synchronized void start() {
if (!run){
run = true;
}
}
public synchronized void stopProcess() {
if (run){
run = false;
}
}
public boolean isRunning(){
return this.run;
}
protected void wakeExecutor(){
if (processThread ==null || !processThread.isAlive()){
processThread = new Thread(new Runnable() {
#Override
public void run() {
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
});
processThread.start();
}
}
}
It is important, that data must to process in the order, in which it come from threads.
You are seriously reinventing the wheel here. All you want is available in the JDK in the java.util.concurrent package.
Implement a producer-consumer pattern via a BlockingQueue, with your producers calling offer() and your consumer thread calling take(), which blocks until something's available.
That's it. You don't need, and you shouldn't be writing, all those classes you have written. These concurrent classes do all the locking and synchronization for you, and do it correctly too (which is not to be underestimated)
If you're not allowed to use anything from java.util.concurrent then you'll have to implement your own task queue based on something like a LinkedList. I would encapsulate the blocking behaviour in the queue, e.g. (pseudocode)
synchronized Data nextTask() {
while(the linked list is empty) {
wait()
}
remove and return head of the queue
}
synchronized void addTask(Data d) {
add d to the queue
notifyAll()
}
Then you can just have a consumer thread that continuously does something like this
while(true) {
taskQueue.nextTask().process()
}
and the producer threads call taskQueue.addTask to add each task to the queue. If you need a graceful shutdown at the end then you'll either need some "sentinel value" to tell the consumer thread to finish, or find some way of calling Thread.interrupt() at the right time.
I am trying to get familiar with Java threads for the SCJP and I had a question.
In the below-written code i simply created:
two Runnables with
a common data storage (an array) and
a synchronized write() method to fill it with data successively leaving a letter as a mark for each Runnable (A and B) in sequence.
I know the code is rough and could be better written but I was seeking the moral of the threads.
So now when I run it, it never terminates and the results stop at:
Still good.
A0.
But when I change wait() to wait(100) it works just fine counting from 0 to 9 and it terminates normally. Could someone explain the reason behind that for me please?
Thank you.
public class ArrayThreads {
Object[] array = new Object[10];
boolean isA = true;
int position = 0;
int getIndex(){
return position;
}
class ThreadA implements Runnable{
synchronized void write(String value){
while(!isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("A");}
}
}
class ThreadB implements Runnable{
synchronized void write(String value){
while(isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("B");}
}
}
public static void main(String[] args){
ArrayThreads threads = new ArrayThreads();
Thread threadA = new Thread(threads.new ThreadA());
Thread threadB = new Thread(threads.new ThreadB());
System.out.println("Still good");
threadB.start();
threadA.start();
}
}
Your threads are each waiting and notifying separate objects - so they're not communicating with each other at all. If you want them to effectively release each other, they'll need a shared monitor to synchronize, wait on and notify.
It's "working" when you specify a timeout because it's effectively turning the wait call into a sleep call... still nothing is really waiting/notifying usefully, because the two threads are still dealing with separate monitors.
your objects are not working in same monitor.
you need to either move the wait() and notify() to same object like:
http://www.java-samples.com/showtutorial.php?tutorialid=306
or you can notify the target object:
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ315_016.htm
when you set wait(100). you are setting a timeout. and definitely it will wake up after 100ms.