synchronized increment an int value - java

Why this program doesn`t display 2000 at every execution? I know that I can use AtomicInteger, but I am curious.
class Increment extends Thread{
static Integer i=new Integer(0);
public void run(){
for(int j=1;j<=1000;j++){
synchronized (i) {
i++;
}
}
}
}
public class Puzzle {
public static void main(String args[]) {
Thread t1=new Increment();
Thread t2=new Increment();
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch (InterruptedException r){}
System.out.println(Increment.i);
}
}

You synchronize on a mutable variable i. This variable changes its value each time, therefore each time you acquire a lock on another object. Each thread thus acquires a non-contended lock and can proceed simultaneously, as if no synchronization was in place.
Lesson: use a dedicated private static final Object lock = new Object() as a lock.

Related

How to check whether sleep() method in Java holds lock or not?

class MyThread extends Thread{
public void run(){
print();
}
synchronized public void print() {
// for(int i = 0; i< )
System.out.println("Thread : " + Thread.currentThread().getName());
try{
Thread.sleep(5000);}
catch(InterruptedException e ){
}
}
}
public class MyClass {
public static void main(String args[]) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("A");
t2.setName("B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("EOM");
}
}
Output of the Program -
ThreadA
ThreadB
Immediately prints both line
After 5 seconds
EOM
According to my understanding, one of the thread should go in print() and acquire lock and only releases it after 5 seconds but here both the threads executed immediately and then "EOM" got printed after 5 seconds.
The synchronized is in an instance method, and each instance doesn't interfere with each other.
If the method were static then it would be shared between the instances.
You wrote:
synchronized public void print() {
...
}
That's just a short-cut way of writing:
public void print() {
synchronized(this) {
...
}
}
Each of your two threads is operating on a different instance of your MyClass class, therefore, each of your two threads is synchronizing on a different object (different this reference).
When you use synchronized(o) blocks, that only prevents two different threads from synchronizing on the same object o at the same time.

Why my synchronized method not working properly?

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();
}
}

Why the following code of multithreading is not working? The answer should be 20000 I believe

Why am I not getting 20000 when the increment method is synchronized. I did the same thing with runnable and it worked.
public class ThreadClass extends Thread
{
static int count=0;
public synchronized void increment()
{
count++;
}
public void run()
{
for(int i=0;i<10000;i++)
{
increment();
}
};
}
public class Main {
public static void main(String[] args) {
ThreadClass t1=new ThreadClass();
ThreadClass t2= new ThreadClass();
t1.start();
t2.start();
try {
t2.join();
t1.join();
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println(ThreadClass.count);
}
}
The JLS, for synchronized methods, clearly states the following:
For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
As a result, the two ThreadClass instances will lock independently, and there will be no common lock protecting bad writes to count.
Synchronize explicitly on Threadclass.class or make increment() static to actually synchronize in a manner that makes writes safe.

Multithreading - Synchronizing the block for all instances of an Object

I have a class as Calculate. I created two threads both working on different instances of this class and tried to get the value of i. But both are giving me same values.
I want if one thread of a instance is working then the thread working on other instance should wait.
public class Calculate {
private int i=2;
public void showNumber(){
synchronized(Calculate.class){
i=i+2;
}
System.out.println(Thread.currentThread()+"Value of i is "+i);
}
}
class Test1 implements Runnable{
Calculate c=null;
public Test1(Calculate c){
this.c=c;
}
#Override
public void run() {
System.out.println(Thread.currentThread()+" Running");
c.showNumber();
}
}
public class ThreadingPractise {
public static void main(String[] args) {
Calculate c=new Calculate();
Calculate c1=new Calculate();
Thread t1=new Thread(new Test1(c),"t1");
Thread t2=new Thread(new Test1(c1),"t2");
t1.start();
t2.start();
}
}
make i as static. If you want to share the variable between threads. and synchronize showNumber method instead of Calculate.class so that only 1 thread will run it at a time.

Thread Waits for a lock when it shouldn't be

i am practicing on java threads, and i am confused with Locking mechanism,
What i am trying to achieve is when a thread is taking much time to execute a block of code whose lock it has acquired, the other thread should just not wait and go for the else condition,
this is my code as follows
import java.util.concurrent.locks.*;
import java.util.concurrent.*;
class MySharedData{
private volatile boolean bFlag;
private int counter=1;
public void abuseIt() throws Exception{
while(!bFlag){
System.out.println(" THREAD "+Thread.currentThread().getName()+" WITH COUNTER "+counter);
counter++;
Thread.sleep(1000);
if(counter > 20){
bFlag=true;
}
}
}
}
class RequesterThree implements Runnable{
private Lock lock;
RequesterThree(){
lock = new ReentrantLock();
}
#Override
public void run(){
MySharedData myShared = null;
try{
myShared = new MySharedData();
if(lock.tryLock(250,TimeUnit.MILLISECONDS)){
myShared.abuseIt();
}else{
System.out.println(Thread.currentThread().getName()+": SHARED DATA IS NON-ACCESSIBLE !!!!");
}
}catch(Exception e){
System.out.println(e);
}finally{
lock.unlock();
}
}
}
public class Ex03{
public static void main(String [] args){
Thread[] requests = new Thread[]{
new Thread(new RequesterThree(),"MICHEAL"),
new Thread(new RequesterThree(),"SHAWN"),
new Thread(new RequesterThree(),"JOHN"),
new Thread(new RequesterThree(),"TRON"),
new Thread(new RequesterThree(),"FINCH")
};
for(int x=0; x < requests.length; x++){
requests[x].start();
}
}
}
But here all of the five threads wait for the lock, and not a single thread prints the SOP in the else condition,
What i am expecting is,
When Thread T1 is started, it acquires the lock, and execute the abuseIt() method, there it sleeps for 1 sec,
Now thread T2 should wait for the lock to get free for only 250 milisec, but T1 is any how waiting for 1 sec, so T2 should execute the else condition in the run method,
How can i achieve this,
In your code, each RequesterThree object has a separate lock, so there is no synchronization across them.
Additionally, each thread calls myShared.abuseIt() on its own dedicated instance of MySharedData.
To fix:
private static final Lock lock = new ReentrantLock();
private static final MySharedData myShared = new MySharedData();
Also, remove the constructor and the change the run() method:
#Override
public void run(){
try{
if(lock.tryLock(250,TimeUnit.MILLISECONDS)){
Finally, your code can call unlock() even if tryLock() hasn't succeeded. This needs to be fixed.
Make your lock field final static
...
class RequesterThree implements Runnable{
private static final Lock lock = new ReentrantLock();
RequesterThree(){
}
...

Categories