Synchronized doesn't help to achieve mutual exclusion - java

Class C:
class C extends Thread
{
public static int cr;
C(int n)
{
cr = n;
}
public void run()
{
go();
}
synchronized void go()
{
for (int i = 0; i < 10000; i++)
{
cr++;
}
}
}
Class Launch
class Launch
{
public static void main(String args[]) throws InterruptedException
{
C[] c = new C[10];
for (int i = 0; i < 10; i++)
{
c[i] = new C(0);
}
for (int i = 0; i < 10; i++)
{
c[i].start();
}
System.out.println(C.spaces);
}
}
It doesn't give me 100,000, but rather numbers below 100k. Why? I made method go() synchronized, so it should be used by only one thread at a time..? What am I missing?

synchronized void go(){...} means that it is synchronized on current instance (on this). Since this method belongs to your custom Thread class and you are crating 10 threads there exist 10 different this references.
That is one of the reasons it is preferred to not extend Thread class, but to implement Runnable interface and pass instance of this interface to as many threads as you want.
Another problem is that you are printing edited value without waiting for threads to finish.
What you need is creating one instance which will hold value you want to change and invoke synchronized method from only one instance, because as mentioned by default synchronized void method is synchronized on this (current object on which this method is invoked).
class MyTask implements Runnable {
public volatile int counter;
MyTask(int n) {
counter = n;
}
public void run() {
System.out.println(Thread.currentThread().getName()+" entered run");
go();
System.out.println(Thread.currentThread().getName()+" finished run");
}
synchronized void go() {
System.out.println(Thread.currentThread().getName()+" entered go");
for (int i = 0; i < 10000; i++) {
counter++;
}
System.out.println(Thread.currentThread().getName()+" left from go");
}
}
class Luncher {
public static void main(String args[]) throws InterruptedException {
//lets create task we want to execute in parallel
MyTask task = new MyTask(0);
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)//create thread instances
threads[i] = new Thread(task);
for (int i = 0; i < 10; i++)//start threads
threads[i].start();
for (int i = 0; i < 10; i++)
threads[i].join();//hold main thread to wait till all threads will finish
System.out.println(task.counter);
}
}

with
c[i] = new C(0);
you are creating new instance of c every time
with
synchronized void go()
{
for (int i = 0; i < 10000; i++)
{
cr++;
}
}
you will always get the number less than 10000 i dont know why you are expecting 100,000
Is it a typo mistake i < 10000 where you should have u used 100,000 ?
To answer your last question
I made method go() synchronized, so it should be used by only one thread at a time..?
if only one thread at a time, you don't need synchronized(multithreading concept).

It doesn't give me 100,000, but rather numbers below 100k. Why?
Every thing is working fine but main thread is not waiting for other threads to complete the calculation hence output is random in main thread.
Use Thread#join() so that main thread waits for all the other threads to die before executing the last line of the main thread.
for (int i = 0; i < 10; i++) {
c[i].start();
c[i].join(); // Waits for this thread to die
}
System.out.println(C.cr); // output 100000
It's worth reading How do I pause main() until all other threads have died?

Related

Threads changing the same Variable wont synchronize [duplicate]

This question already has answers here:
Thread safety in java multithreading
(3 answers)
Difference between volatile and synchronized in Java
(4 answers)
Closed 1 year ago.
My problem is that the code should increment a 1000 times and then output it. But sometimes a isn't 1000 at the end.
public class Counter extends Thread {
private static Integer a = 0;
public void run() {
for (int i = 0; i < 100; i++) {
a++;
}
}
public static void main(String[] args) {
Counter[] ca = new Counter[10];
for (int i = 0; i < 10; i++) {
ca[i] = new Counter();
ca[i].start();
}
for (Counter c : ca) {
try {
c.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(a);
}
This code is the original code that is obviously not going to work because I have multiple Threads accessing the variable a. I've tried putting a synchronized(this) around a++; and marking a as volatile but I still sometimes get a false Result. The only way I've found to make it work reliably it to put join() into the for loop, but that kind of defeats the point of using Threads in the first place.
Any help is appreciated.
There are several problems in the code you posted, and all them a reported in the comments to your qestion.
I try to show the major ones:
Variable a is Integer which is immutable, this means that a++ really means create a new Ineger instance containing the old value plus 1.
the variable a is updated by multiple threads concurrenlty without synchonizazion, this means that the operation a=a+1 canbe split in read a, increment a; if two or more thread read a at the same time the the increment by one the same value
Here is a modified version that uses a Lock to synchronize access to the resource. The main scope of this code is to show that the access to a must be synchronixed between thread; in order to get a "clean design" you must refactor/change a lot of other things.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncProblem {
private static int a=0;
private static class IncThread extends Thread {
private Lock lock;
public IncThread(Lock lock) {
this.lock=lock;
}
public void run() {
lock.lock();
try {
for (int i = 0; i < 100; i++) {
a++;
}
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
Lock lock= new ReentrantLock();
IncThread[] ca = new IncThread[10];
for (int i = 0; i < 10; i++) {
ca[i] = new IncThread(lock);
ca[i].start();
}
for (IncThread c : ca) {
try {
c.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(a);
}
}

How do I fix the 'threads cannot be resolved to a variable' error?

public class UnsynchronizedCounterTest{
/**
* A class representing a counter with a method for incrementing the coutner. No synchronization is used
* so this counter is not thread safe
* #author
*
*/
static class Counter{
int count;
void inc() {
count = count+1;
}
int getCount() {
return count;
}
}
static Counter counter; // The counter that will be incremented. Since it is a global static variable, it is used by all threads of type HWUExercise12_1Thread. It is shared resource
static int numberOfIncrements;
static class IncrementerThread extends Thread{
public void run() {
for (int i=0; i < numberOfIncrements; i++) {
counter.inc();
}
}
}
/**
* The main program runs in a loop until the user want to exit. Each time through the loop, it runs one experiemtn.
* It gets the number of threads and the number of increments per thread from the user. It creates and starts the
* threads, and then waits for all to finsih. It prints the fibna lvalue of the counter, as well as the expected value.
* The program ends when the user enters a number less than or equal to zero as the number of threads.
* #param Args
*/
public static void main(String Args[]){
Counter counter = new Counter();
Scanner reader = new Scanner(System.in);
while(true) {
System.out.print("Enter the number of threads");
int numberOfThreads = Integer.parseInt(reader.nextLine());
if (numberOfThreads < 0) {
break;
}do {
System.out.print("Enter the number of increments per thread");
int numberOfIncrements = reader.nextInt();
//create thread array
IncrementerThread [] threads = new IncrementerThread[numberOfThreads];
//Create a thread for each position in array
for (int i=0; i< threads.length; i++) {
threads[i] = new IncrementerThread();
}
}while (numberOfIncrements <= 0);
//start the threads
for (int i=0; i < numberOfThreads; i++) {
threads[i].start();
}
try {
for(int j=0; j< numberOfThreads; j++) {
threads[j].join();
}
System.out.println("The finanl value of the counter is" + counter.getCount());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
For this program, I created a thread class (not thread-safe) that calls the inc () method in the nested class, a specified number of times. My program is supposed to create several threads and start them all and then wait for all the threads to terminate. I also have to print the final value of the counter. My error is that the eclipse is saying the the thread array I created, threads cannot be resolved to a variable. It's giving me an error for the lines
threads[i].start();
threads[j].join();
I'm a beginner in java and I'm not sure how to fix this issue. My question is that why is it saying threads cannot be resolved to a variable when I clearly have a thread object array? Thanks.
This is a working code:
public class UnsynchronizedCounterTest{
static Counter counter;
public static void main(String Args[]){
new UnsynchronizedCounterTest().startCounting();
}
public void startCounting() {
counter = new Counter();
Scanner reader = new Scanner(System.in);
while(true) {
System.out.print("Enter the number of threads: ");
int numberOfThreads = reader.nextInt();
if (numberOfThreads <= 0) {
break;
}
IncrementerThread [] threads;
do {
System.out.print("Enter the number of increments per thread");
numberOfIncrements = reader.nextInt();
//create thread array
threads = new IncrementerThread[numberOfThreads];
//Create a thread for each position in array
for (int i=0; i< threads.length; i++) {
threads[i] = new IncrementerThread();
}
}while (numberOfIncrements <= 0);
//start the threads
for (int i=0; i < numberOfThreads; i++) {
threads[i].start();
}
try {
for(int j=0; j< numberOfThreads; j++) {
threads[j].join();
}
System.out.println("The finanl value of the counter is: " + counter.getCount());
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
class IncrementerThread extends Thread{
#Override
public void run() {
for (int i=0; i < numberOfIncrements; i++) {
counter.inc();
}
}
}
class Counter{
int count = 0;
void inc() {
count = count+1;
}
int getCount() {
return count;
}
}
}

volatile example (that in JLS8/8.3.1.4 volatile Fields) not work?

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4
Java Language Specification 8/8.3.1.4 volatile Fields
volatile example
Question:
In the example of volatile, I add synchronized keyword to method two() to avoid executing one() during method two().
But I still noticed j is larger than i: why ?
Note:
I use Java HotSpot 1.8.0_112.
If you can not noticed j is larger than i, please set testVolatile()/num to a larger number.
My demo:
public class VolatileDemo {
static volatile int i = 0, j = 0;
static void one() {
i++;
j++;
}
static synchronized void two() {
if (i != j)
System.out.println("i=" + i + " j=" + j);
}
static void testVolatile() {
int num = 5000;
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
public void run() {
one();
}
}).start();
}
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
public void run() {
two();
}
}).start();
}
}
public static void main(String[] args) {
testVolatile();
}
}
My result:
i=4996 j=4998
i=4998 j=5000
i=4998 j=5000
....
It's possible and it's described in the link you mentioned. It's at the end of the paragraph.
It is possible, however, that any given invocation of method two might observe a value for j that is much greater than the value observed for i, because method one might be executed many times between the moment when method two fetches the value of i and the moment when method two fetches the value of j.
So two() method reads i and then j with the exact order as in your code. But there are a cople of one() method calls between that reads which gives the result of (4998, 5000)

What is the proper way to let threads print out sequentially using join

I am curious about how to let the threads print out sequentially using join().(Any other ways are also welcome.) For example, I have the code as following:
private static class LittleThread implements Runnable {
int val;
public LittleThread(int i) {
val = i;
}
public void run() {
System.out.println("Thread " + val + " finished.");
}
}
public static void main(String[] args) throws Exception {
for (int i = 1; i <= 10; i++) {
new Thread(new LittleThread(i)).start();
}
}
I am wondering, how do we do with this code, to make the main() prints sequentially:
Thread 1 finished.
Thread 2 finished.
Thread 3 finished.
...
To make a number of Runnable objects, executed in a separate Thread, execute sequentially, you should use the single thread ExecutorService:
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
executor.submit(new LittleThread(i));
}
executor.shutdown();
}
The ExecutorService is responsible for proper management of the Thread objects (ok, all one of them in this case) ... creating them (it) as needed, and terminating them by calling join (as the service is shutdown).

Java multithreading not thread-safe using synchronized

A simple multithreading test with synchronization. I thought if it was "synchronized," other threads would wait. What am I missing?
public class MultithreadingCounter implements Runnable {
static int count = 0;
public static void main(String[] args) {
int numThreads = 4;
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++)
threads[i] = new Thread(new MultithreadingCounter(), i + "");
for (int i = 0; i < numThreads; i++)
threads[i].start();
for (int i = 0; i < numThreads; i++)
try {
threads[i].join();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
increment();
}
public synchronized void increment(){
System.out.print(Thread.currentThread().getName() + ": " + count + "\t");
count++; // if I put this first or increment it directly in the print line, it works fine.
}
}
I thought this would display something like:
0: 1 2: 0 1: 2 3: 3
But its actual output:
0: 0 2: 0 1: 0 3: 3
and other variations like this. It should display each increment (i.e. 0,1,2,3) not in order...
Your synchronized keyword is on an instance method. No two threads can execute this method of one of your thread objects at the same time. But, that is not what your code does. Each thread executes the method on its own instance. The synchronization does not do what you seem to intend. If it were a static method, it would.
Your increment method should be static:
public static synchronized void increment() {
Right now, each object is synchronized on that individual instance, but since count is a static variable, you should be synchronizing on the Class object itself.
when synchronized keyword is used before a method, it ensures that that method can be executed by only one thread at a time with respect to that object only. It does not ensure thread safety from other objects.

Categories