Java Multithreading synchronized usage [duplicate] - java

This question already has answers here:
Synchronized block not working
(8 answers)
Closed 3 years ago.
I am confused as to what will be the output of the following code(between the two options) and why:
As per my understanding output should be option1 as synchronized keyword is used .
Output Options:
Java Thread ThreadExample JavaMultithreading.
The order in which text will be printed cannot be determined.
class ThreadDemo extends Thread
{
final StringBuffer sb1 = new StringBuffer();
final StringBuffer sb2 = new StringBuffer();
public static void main(String args[])
{
final ThreadDemo h = new ThreadDemo();
new Thread()
{
public void run()
{
synchronized(this)
{
h.sb1.append("Java");
h.sb2.append("Thread");
System.out.println(h.sb1);
System.out.println(h.sb2);
}
}
}.start();
new Thread()
{
public void run()
{
synchronized(this)
{
h.sb1.append("Mutithreading");
h.sb2.append("Example");
System.out.println(h.sb2);
System.out.println(h.sb1);
}
}
}.start(); }}

First, there is no telling which thread will run before the other. So you can't assert definitely that "Java thread" will precede "Mutithreading Example". It might happen, it might not.
Second, the synchronized keyword on the run methods is irrelevant, because each thread is locking on its own monitor. So there's no reason to think that "Java" and "thread", for instance, have to be printed together without anything in between. It might happen, it might not.
The locks that do matter here are on the StringBuffers, and on the stdout PrintStream. These objects use synchronized on their methods, acquiring the monitor and holding it for the duration of the method call. That prevents concurrent calls modifying the state of the same object from interfering with each other.

Related

My concurrent code is synchronised but it is not printing values in sync however each thread prints the same value

I am trying to demonstrate how to fix a RaceCondition using the synchronized keyword. The below code consists of a ZooStock objects' variable being incremented and printed by 4 threads. I have synchronized the method (addGrass()) however the values being printed by all threads are the same i.e.
Current output: 1002g, 1002g, 1002g, 1002g
Expected output: 1001g, 1002g, 1003g, 1004g
public static void main(String[] args){
ZooStockSync zooStockNew = new ZooStockSync(1000, 750, 5000);
ExecutorService executorService = null;
try{
executorService = Executors.newFixedThreadPool(10); //Creating a Thread pool of size 10
for(int i=0; i<4; i++){
executorService.submit(()->new ZooWorkerSync(zooStockNew).addGrass()); //
}
}finally{
if(executorService != null) executorService.shutdown();
}
}
Class containing synchronized method:
class ZooWorkerSync implements Runnable {
ZooStockSync zooStock;
ZooWorkerSync(ZooStockSync zooStock){
this.zooStock = zooStock;
}
public synchronized void addGrass(){
zooStock.grass++;
System.out.print(zooStock.grass + "g ");
}
}
However when I create Threads in a traditional (java.lang.Thread) sense without using the Executor threads from java.util.concurrent package.
public static void main(String[] args){
ZooStockSync zooStockTraditional = new ZooStockSync(1000, 750, 5000);
ZooWorkerSync[] workerThreads = new ZooWorkerSync[4]; //Set all elements in the array to be a ZooWorker object
Arrays.fill(workerThreads, new ZooWorkerSync(zooStockTraditional));
for (ZooWorkerSync workerThread : workerThreads) {
new Thread(workerThread).start(); //Start the worker threads off (this invokes the run method in the ZooWorker class)
}
}
The output is as expected: 1001g 5010w 751h 1002g 5020w 752h 1003g 5030w 753h 1004g 5040w 754h, notice the g's are in ascending order as expected. (Ignore the h's and w's)
The worker thread's run method is shown below:
#Override
public void run() {
addGrass();
addWater();
addHay();
}
So my question is, why do the 2 outputs differ, why am I getting the same value printed using the java.util.concurent Executors' threads opposed to the traditional method?
In your ExeutorService example, you're creating multiple instances of the ZooWorkerSync class, in the Thread example you're reusing the same instance.
In your first example, the synchronized keyword doesn't really do anything since it's an instance level lock. You could try manually synchronizing on the class instead.
synchronized locks an object, and because you are sync'ing on multiple object, it isn't working as you'd like.
Instead, you should synchronize on a common object, like the class.
class ZooWorkerSync implements Runnable {
ZooStockSync zooStock;
ZooWorkerSync(ZooStockSync zooStock){
this.zooStock = zooStock;
}
public void addGrass(){
synchronized (ZooWorkerSync.class) {
zooStock.grass++;
System.out.print(zooStock.grass + "g ");
}
}
}
I don't see the code for ZooStockSync but it looks like you're synchronizing a method on the thread (ZooWorkerSync) and not the object being shared. You then access a field in ZooStockSync:
public synchronized void addGrass(){
zooStock.grass++;
System.out.print(zooStock.grass + "g ");
}
But access to that field (grass) may not be thread safe. Each ZooWorkerSync thread can access that field simultaneously. I would suggest putting synchronized on a method in ZooStockSync that increments the field. For example:
public synchronized void incrementGrass() {
grass++;
}
You can also use the volatile keyword for the grass field, or make it an AtomicInteger.
The error arises from me creating several instances of ZooWorkerSync in the Executors example, the use of the word synchronized as demonstrated above works as an instance level lock, so it is practically redundant across multiple instances, it will only be useful for a single instance, hence I need to modify my executorService to only invoke addGrass() from a single instance:
public static void main(String[] args){
ZooStockSync zooStockNew = new ZooStockSync(1000, 750, 5000);
ExecutorService executorService = null;
try{
executorService = Executors.newFixedThreadPool(10); //Creating a Thread pool of size 10
ZooWorkerSync zooWorkerSync = new ZooWorkerSync(zooStockNew);
for(int i=0; i<4; i++){
executorService.submit(zooWorkerSync::addGrass);
}
}finally{
if(executorService != null) executorService.shutdown();
}
}

same variable getting used by different threads is getting updated inside synchronized block

There might be a straightforward for this issue, but I am not understanding the concept here.
I am trying a simple program where I am having 3 threads executing a synchronized block to print letter in an incrementing order.The synchronized block is having lock on the variable(which is a StringBuffer object). Below is the code:
public class SimpleThread extends Thread implements Runnable{
private StringBuffer myBuffer;
public StringBuffer getMyBuffer() {
return myBuffer;
}
public void setMyBuffer(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public SimpleThread(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public void run() {
synchronized (this.myBuffer) {
while((int)(this.myBuffer.charAt(0))!=68) {
for(int i=0;i<3;i++) {
System.out.println(this.myBuffer.charAt(0));
}
char x = this.myBuffer.charAt(0);
this.myBuffer.setCharAt(0, (char) (x+1));
}
//this.myBuffer.setCharAt(0, 'A');
}
}
public static void main(String[] args) {
StringBuffer safeBuffer = new StringBuffer();
safeBuffer.append('A');
SimpleThread one = new SimpleThread(safeBuffer);
one.setName("One");
one.start();
SimpleThread two = new SimpleThread(safeBuffer);
two.setName("Two");
two.start();
SimpleThread three = new SimpleThread(safeBuffer);
three.setName("Three");
three.start();
}
Output for the program is:
A
A
A
B
B
B
C
C
C
It is only printing the value when thread One is executing and for other two threads, the of variable myBuffer is becoming D. What I don't understand is why changing the variable for one object reflect for other objects?
synchronized means only one thread can execute the code block at a time. You might be confusing the wording to think it synchronizes the variable.
When you write synchronized (this.myBuffer), you are telling the program to use myBuffer as a lock when deciding if a thread can execute the following code block.
This means when a thread tries to execute synchronized (this.myBuffer) { } it will attempt to get the lock on myBuffer.
If no other thread has the lock, it will obtain it and execute the
code block.
If another thread has the lock it will wait until the other thread releases the lock (usually by finishing running the code inside the code block).
That means all threads will always take turns executing the contents of synchronized (this.myBuffer) { }.
Since thread "One" is started first, it will get the lock first and finish all the work it has thus incrementing the myBuffer content to D, before handing it over to thread "Two".

Why the program run last much more time than 3 seconds? [duplicate]

This question already has answers here:
Thread won't stop when I want it to? (Java)
(2 answers)
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 4 years ago.
I have tested something about multithreading. I find the snippet lasts much more than 3 seconds, and is not printing the last System.out.println("program end");. Why?
public class hello {
static Boolean flag = false;
public static void main(String args[]) throws InterruptedException {
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
hello.flag = true;
}
static class MyThread extends Thread {
public void run(){
System.out.println("Thread start");
while(true){
if(hello.flag){
break;
}
}
System.out.println("Thread end");//why not print this statement? but run in debug mode, it will print this statement correctly
}
}
}
program run result as follow:
Different threads use different memory space caches each.
It means the first thread has the variable in its own cache, and the other thread has the variable in its own cache. Thus each thread seeing the same variable in different states.
In the absence of appropriate synchronization mechanisms between the two thread, they have no reason to try and reconcile the difference in their caches. It would severely deter performances to do that without being instructed to.
One very easy synchronization mechanism you could have here, would be to make variable flag, volatile. That will make the threads synchronize their caches on this variable on each read/write.
Use volatile with flag to make thread read actual value of flag not from its local cache..
public class hello {
//make flag volatile
volatile static Boolean flag = false;
public static void main(String args[]) throws InterruptedException {
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
hello.flag = true;
}
static class MyThread extends Thread {
public void run(){
System.out.println("Thread start");
while(true){
if(hello.flag){
break;
}
}
System.out.println("Thread end");//why not print this statement? but run in debug mode, it will print this statement correctly
}
}
}
Please go through below link to see how it works..
https://docs.oracle.com/cd/E19683-01/806-5222/codingpractices-1/index.html

How could the two threads enter the synchronized block at the same time?

There is some weird thing happening. As I enter the synchronized block,I try to print the name of the Thread.After the print statement,I make a husge pause of 100000 seconds.
#Override
public int getNextAvailableVm() {
synchronized(this) {
System.out.println(Thread.currentThread().getName());
try {Thread.sleep(100000000);}catch(Exception exc){}
String dataCenter = dcc.getDataCenterName();
int totalVMs = Temp_Algo_Static_Var.vmCountMap.get(dataCenter);
AlgoHelper ah = (AlgoHelper)Temp_Algo_Static_Var.map.get(dataCenter);
.
.
.
}
}
But as this method is run,name oft the 2 threads are printed.
Thread-11
Thread-13
and it is after this that the long pause occurs. Why is that ? How could the two threads enter the synchronized block,when the first thread has yet not left the block ?
If the two threads are running against the same object then this should not happen.
I would therefore suggest that you are creating a new object for each thread or at least some of the threads are running on different objects.
If you do want multiple objects then you should not use synchronized(this), you should create a static final Object to synchronize on. Please do not sync on this.getClass() as that breaks.
Most likely you are invoking getNextAvailableVm() on different instances of the containing class. Since you are synchronizing on this you will be locking on two different monitors (first thread locks on instance1, second one on instance2).
There are a lot of ways you could correct this:
make the whole method synchronized
synchronize on this.getClass()
define a static object to lock on
use methods from java.util.concurrent.locks to do the locking
These are just some suggestions to address your problem, but to find the right one we would have to know more about your application structure and your requirements.
I guess the below prog, will work like you expected,
Locked on Thread1.Class, Two thread will not execute the method simultaneously
public class Test {
public static void main(String [] args) {
Thread1 t1 = new Thread1();
Thread1 t2 = new Thread1();
t1.start();
t2.start();
}
}
class Thread1 extends Thread{
public void run(){
getNextAvailableVm();
}
public void getNextAvailableVm() {
synchronized(Thread1.class) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
}catch(Exception exc){}
System.out.println(Thread.currentThread().getName());
}
}
}
OUTPUT
Thread-1
Thread-1
Thread-0
Thread-0

In Java 7 64-bit my program freezes on a loop [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
This is my simple program:
public class Test {
public static Object obj = null;
public static void main(String[] args) {
obj = null;
System.out.println("Start");
MyThread myThread = new MyThread();
myThread.start();
while(obj == null) {
//System.out.println("");
}
System.out.println("Stop");
}
}
class MyThread extends Thread {
#Override
public void run() {
System.out.println("Thread 1");
try {
sleep(1);
} catch (InterruptedException ex) {
}
System.out.println("Thread 2");
Test.obj = new Object();
System.out.println("Thread 3");
}
}
As you can see, I run MyThread thread and while loop of Test class. The loop checks if obj is null and if it is not, I stop it and print "2". MyThread assigns a value to obj. And now the problem:
Under Java 7 64-bit, in case of empty while loop, it is never stopped. However, if I uncomment System.out.print(""), "Stop" under the loop is printed. But for other statements inside the loop (e.g. int i = 1;) my program freezes. Under Java 32-bit everything works fine for all cases.
Could someone explain me this strange behaviour?
Thanks!
Your code is not thread-safe. The assignment you make to Test.obj in the thread aren't guaranteed to be visible in the main thread without some form of synchronization.
Make that static variable private, and provide synchronized static getter/tester/setter methods would be one way of implementing this correctly (as long as all accesses go through these methods). Other alternatives exist.
Remember that that there is also volatile keyword in Java.
In case of this particular example - Java caches your obj.

Categories

Resources