Why is this freezing code

In the code below, when I execute the producercon class, sometimes executable stucks, looks like a dead end. But if I do get_flag () synchronization then there will be no such problems.

I can’t understand how the problem could be. flag can be true or false, so only one of producer or consumer gets into the if . After one of them enters if , it enters the monitor with object r (both are initialized with the same object reference). The only problem that can happen is that the object r , which changes when the function increment_decrement () called, and get_flag () , reads the flag at the same time, but even then it will not enter if in this iteration, but it will go into the if block on the next iteration, and even if the first thread does not leave the monitor, it will wait for it there (before the synchronized block).

How and why does the program stop / hang if get_flag () not made synchronized ?

 import java.io.*; class resource { private boolean res, flag; resource () { flag=false; } boolean get_flag () { return flag; } void increment_decrement (String s,boolean t) { res=t; flag=t; try { System.out.print("\n"+s+":"+res); Thread.sleep(200); } catch(InterruptedException e) { } } } class producer implements Runnable { resource r1; Thread t1; producer(resource r) { r1 = r; t1 = new Thread(this); t1.start(); } public void run () { while (true) { if(r1.get_flag () == false) { synchronized(r1) { r1.increment_decrement("Producer",true); } } } } public void waitForThread () throws InterruptedException { t1.join (); } } class consumer implements Runnable { resource r2; Thread t2; consumer(resource r) { r2 = r; t2 = new Thread (this); t2.start(); } public void run() { while (true) { if(r2.get_flag () == true) { synchronized(r2) { r2.increment_decrement("Consumer",false); } } } } public void waitForThread () throws InterruptedException { t2.join (); } } public class producercon { public static void main(String args[]) { try { System.out.print("PRESS CTRL+C TO TERMINATE\n"); resource r = new resource(); consumer c = new consumer(r); producer p = new producer(r); c.waitForThread (); p.waitForThread (); } catch(InterruptedException e) { } } } 
+4
source share
3 answers

Your call to get_flag () is not thread safe and unstable. This means that in the cache of thread 1 it can be true, and in the cache of thread 2 it can be false.

+6
source

You need to make the boolean value volatile or AtomicBoolean . Right now, several threads are trying to access a logical state that is in no way synchronized.

+4
source

This manufacturer / consumer implementation is rather strange.

Neither the producer nor the consumer waits until the resource is in the appropriate state, and access to the resources is not sufficiently protected (the flag must be protected with some kind of blocking to ensure its visibility between threads).

One way to improve this design is to use a standard standby / notification system. Another way would be to use the Semaphore in the Resource to ensure that only one thread can access the resource at a given point in time. Finally, you can use a higher-level construct, such as java.util.concurrent.SynchronousQueue, to transfer some data directly from the producer to the consumer.

0
source

Source: https://habr.com/ru/post/1385557/


All Articles