I am trying to learn synchronization. Got stuck here according to what I have learned the following code should give 8000 as the final result but I am getting a random result like below
package threads;
import java.time.LocalDateTime;
public class A implements Runnable {
String name;
static Integer j=0;
A(String name){
this.name=name;
}
#Override
public synchronized void run() {
for(int i=1;i<=1000;i++){
synchronized(this){
A.j++;
}
}
System.out.println(j);
}
package threads;
public class MainClass {
public static void main(String args[]){
Thread t1=new Thread(new A("i am thread A "));
Thread t2=new Thread(new A("i am thread B "));
Thread t3=new Thread(new A("i am thread C "));
Thread t4=new Thread(new A("i am thread D "));
Thread t5=new Thread(new A("i am thread E "));
Thread t6=new Thread(new A("i am thread F "));
Thread t7=new Thread(new A("i am thread G "));
Thread t8=new Thread(new A("i am thread H "));
t1.setPriority(Thread.MAX_PRIORITY);
t8.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
still getting output like 1293
2214
1403
3214
4214
5214
6224
7037
can anyone explain to me how to achieve synchronization and what is going wrong here?
It is a common mistake to think that synchronized means "critical section", and that no other threads will run while a synchronized block is running. But synchronized blocks are only exclusive with respect to other synchronized blocks that lock on the same lock.
The answers you got ("use a common lock") are right, but didn't really tell you why. The other common mistake is to think about synchronized as protecting code, when really you should be thinking about it protecting data. Any shared mutable data should be guarded by one and only one lock, and you should know exactly what that lock is. (The more complex your locking scheme, the less likely you'll know what locks guard what data.) So you should always be thinking in terms of "data X is guarded by lock L", and then make sure you acquire lock L whenever you access (read or write) that data.
This will solve the issue. You have to synchronize using a shared lock to all the threads since you are incrementing a static field. Otherwise each object will have it's own lock and increment the static field in parallel leading to a race condition. That's why you are not getting correct value which is 8000 in this case.
package bookmarks;
public class A implements Runnable {
String name;
static Integer j = 0;
private static Object lock = new Object();
A(String name) {
this.name = name;
}
#Override
public void run() {
for (int i = 1; i <= 1000; i++) {
synchronized (lock) {
A.j++;
}
}
System.out.println(j);
}
}
There are a couple of issues in the code.
Issue 1: Lock object added in synchronized(..) is not shared among
all thread instances
Issue 2: System.out.println(j); line should be in the end after t8.join(); otherwise, you will be given 8 times output.
The rectified code
public class A implements Runnable {
String name;
static Integer j = 0;
static Object lockObject = new Object();
A(String name) {
this.name = name;
}
#Override
public void run() {
for (int i = 1; i <= 1000; i++) {
synchronized (lockObject) {
A.j++;
}
}
}
public static void main(String args[]) {
Thread t1 = new Thread(new A("i am thread A "));
Thread t2 = new Thread(new A("i am thread B "));
Thread t3 = new Thread(new A("i am thread C "));
Thread t4 = new Thread(new A("i am thread D "));
Thread t5 = new Thread(new A("i am thread E "));
Thread t6 = new Thread(new A("i am thread F "));
Thread t7 = new Thread(new A("i am thread G "));
Thread t8 = new Thread(new A("i am thread H "));
t1.setPriority(Thread.MAX_PRIORITY);
t8.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(A.j);
}
}
Related
I am trying to get the time it takes the CPU to perform a context switch so I have a class taking the System time in nanoseconds and I put it into some threads but I need to get those numbers and perform computations on it but I don't know how I can access it.
This is my main function.
public class GroupNinePipe{
public static void main(String[] args)
{
Thread t1 = new Thread(new OSProj2("Thread1"));
Thread t2 = new Thread(new OSProj2("Thread2"));
Thread t3 = new Thread(new OSProj2("Thread3"));
Thread t4 = new Thread(new OSProj2("Thread4"));
Thread t5 = new Thread(new OSProj2("Thread5"));
Thread t6 = new Thread(new OSProj2("Thread6"));
OSProj2 n = new OSProj2("Thread 8");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
Class taking system time.
public class OSProj2 implements Runnable {
String name;
long time;
public OSProj2(String x)
{
name = x;
}
public void run()
{
try{
time = System.nanoTime();
System.out.printf("%s sys time: %d\n", name, time);
this.getTime();
}
catch (Exception e){}
}
public long getTime()
{
return time;
}
}
I know the name of the class says Pipe but I don't use one.
I dont know if this is the right way to go about it but nevertheless, your code becomes like this
Runnable osProj2 = new OSProj2("Thread1");
Thread t1 = new Thread(osProj2);
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(osProj2.getTime()); // for example
The t1.join() will block until your thread finish running, hope i helped
I have this synchronized method that prints counter, I have 4 Threads so I am expecting final value of my counter to be 400000 as my counter is a static variable.
but every time I run my code, it is giving me different values of counter.
Following is my code:
class MyThread implements Runnable{
private static int counter=1;
#Override
public void run() {
try {
this.syncMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void syncMethod() throws InterruptedException{
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+" : "+counter++);
}
}
}
public class MyController {
public static void main(String[] args) throws InterruptedException {
Runnable r1=new MyThread();
Runnable r2=new MyThread();
Runnable r3=new MyThread();
Runnable r4=new MyThread();
Thread t1;
Thread t2;
Thread t3;
Thread t4;
t1=new Thread(r1,"Thread 1");
t2=new Thread(r2,"Thread 2");
t3=new Thread(r3,"Thread 3");
t4=new Thread(r4,"Thread 4");
t2.start();
t1.start();
t3.start();
t4.start();
}
}
The variable is static, but the method that you synchronized is not static. This means that it will acquire the monitor on the current instance, and every thread has a different current instance.
A simple solution is to make the syncMethod method static as well; in that case, it will take a lock on the monitor that is shared by all instances of the MyThread class:
public static synchronized void syncMethod()
Erwin Bolwidt's answer is right to solve your problem. As another way to increment a static shared counter in multiple threads safely, you can turn to AtomicLong.
Define it as this:
private static AtomicLong counter = new AtomicLong();
Increment it as:
counter.getAndIncrement();
And in the end, get the result:
counter.get();
synchronised key word in non static methods means exactly synchronize me for this methods : this two code a striclty equivalent :
public synchronised void dojob(){
//the job to do
}
et
public void dojob(){
synchronised (this){
//the job to do
}
}
in your case your synchronized methods are synchronizing on different object (t1,t2,t3 and t4) so didn't block them each other . the best solution is thaat your thread will use a common object to synchronized each other. an other point it alway better to get its thread back to do this call join here is a code to do what you want with this 2 fixes
class MyThread implements Runnable {
public static class JobDoer {
public synchronized void syncMethod() throws InterruptedException {
for (int i = 0; i < 100000; i++) {
System.out.println(Thread.currentThread().getName() + " : " + counter++);
}
}
}
private static int counter = 1;
public MyThread(JobDoer doer) {
this.doer = doer;
}
private JobDoer doer;
#Override
public void run() {
try {
doer.syncMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
JobDoer doer = new JobDoer();
Thread t1 = new Thread(new MyThread(doer), "Thread 1");
Thread t2 = new Thread(new MyThread(doer), "Thread 2");
Thread t3 = new Thread(new MyThread(doer), "Thread 3");
Thread t4 = new Thread(new MyThread(doer), "Thread 4");
t2.start();
t1.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
}
}
This question already has answers here:
What's the difference between Thread start() and Runnable run()
(14 answers)
Closed 7 years ago.
Consider this simple try for a multithreading example :
public class LetsMutexThreads {
public static Object MUTEX = new Object();
private static class Thread1 extends Thread {
public void run() {
synchronized (MUTEX)
{
System.out.println("I'm thread 1 , goint to take a nap...");
try
{
MUTEX.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("T1 : That's it , I'm done ...");
}
}
}
private static class Thread2 extends Thread {
public void run() {
synchronized (MUTEX)
{
System.out.println("Thread 2 : Let's rock N roll !");
System.out.println("Waking up my buddy T1 ...");
MUTEX.notify();
}
}
}
public static void main(String[] args)
{
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.run();
t2.run();
}
}
I'm trying to allow Thread1 to go to sleep with the wait , and then let Thread2
to use notify() to wake Thread1 , but he doesn't get a chance .
Why does the wait() of Thread1 affects the Main Thread from executing t2.run(); ?
You must not attempt to start a thread using the run() method. It does not actually create a new thread, it runs the code in the current thread. Use thread.start() instead in order to have your code executed in a separate (new) thread
This is wrong:
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.run();
t2.run();
Change it to this:
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.start();
t2.start();
I'm writing a small program to see how multiple threads can be run in Java. Not sure why I'm not getting any output:
class NuThread implements Runnable {
NuThread() {
Thread t = new Thread(this, "NuThread");
t.start();
}
public void run() {
try {
for (int i=0; i<5; i++) {
Thread th = Thread.currentThread();
System.out.println(th.getName() + ": " + i);
Thread.sleep(300);
}
} catch (InterruptedException e) {
Thread th = Thread.currentThread();
System.out.println(th.getName() + " interrupted.");
}
}
}
public class MultiThreadDemo {
public static void main(String[] args) {
NuThread t1, t2, t3;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main interrupted.");
}
}
}
You're not creating any instances of NuThread. This line:
NuThread t1, t2, t3;
... just declares three variables. It doesn't create any instances. You'd need something like:
NuThread t1 = new NuThread();
NuThread t2 = new NuThread();
NuThread t3 = new NuThread();
Having said that, making a constructor start a new thread is a little odd in itself... it might be better to remove that and just have:
// TODO: Rename NuThread to something more suitable :)
NuThread runnable = new NuThread();
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.start();
t2.start();
t3.start();
Note that it's okay to use the same Runnable for all three threads, as they don't actually use any state.
You are not creating object of NuThread. That's why thread is not starting.
And it's not the best idea to start thread in the constructor, see here.
Since you are using a Thread, the code further below might give results like:
waiting...One
waiting...Three
waiting...Two
Notified...Two
Notified...Three
Then the code is running until it hits a dead lock. Why is Notified...One missing in the output above? Needs explanation ... (You can get similar result as above when executing following code several time)
class A {
synchronized void waitThread(String threadName) {
System.out.println("waiting..." + threadName);
try {
wait();
} catch(InterruptedException e) { }
System.out.println("Notified..." + threadName);
}
synchronized void notifyThread() {
notifyAll();
}
}
class T1 extends Thread {
A a;
T1(A r, String n) {
a = r;
setName(n);
}
public void run() {
a.waitThread(getName());
}
}
class T2 extends Thread {
A a;
T2(A r, String n) {
a = r;
setName(n);
}
public void run() {
a.notifyThread();
}
}
public class DemoWait {
public static void main(String args[]) {
A a1 = new A();
T1 t1 = new T1(a1,"One");
T1 t2 = new T1(a1,"Two");
T1 t3 = new T1(a1,"Three");
t1.start();
t2.start();
t3.start();
T2 t = new T2(a1,"Four");
t.start();
}
}
You simply have a race condition. It's possible that the thread referenced by the variable t executes notifyAll() before the thread referenced by t1 executes the waitThread(..) method. This is not deadlock. Some of your waits just happen after your notifyAll().
You are facing the problem of Spurious wakeup.So what is happening that the thread which is notifying the all other thread might be call earlier of other thread and after that other thread will run and wait for the wake up.Because of spurious wake up some thread complete.
Change your code...
class A{
boolean flag=true;
synchronized void waitThread(String threadName){
System.out.println("waiting..."+threadName);
try{
while(flag){
wait();
}
}catch(InterruptedException e){ }
System.out.println("Notified..."+threadName);
}
synchronized void notifyThread(){
flag=false;
notifyAll();
} }