When I try to execute the piece of code, I am getting output like 12221121212121221212. When I declare the method as synchronized, it should not allow the other thread to take over the control
package com.test;
public class TestProject extends Thread {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(getName());
}
}
}
public static void main(String[] args) throws InterruptedException {
TestProject myProject = new TestProject();
TestProject myProject1 = new TestProject();
myProject.setName("1");
myProject1.setName("2");
myProject.start();
myProacject1.start();
}
}
So, how do I alter the code to get a output of 11111111112222222222 or 22222222221111111111 in sequential format?
You are synchronizing on this, i.e. on the TestProject object. Since you have two separate objects, you have two separate locks. Consequently, both threads can enter the synchronized section irrespective of what the other thread is doing.
To synchronize across instances of TestProject you need a static lock:
public class TestProject extends Thread {
private static final Object lock = new Object();
public void run() {
synchronized (lock) {
...
Java uses biased locking by default. This means a lock will favour the last thread to access a lock. If you consider that one thread can start, run and finish before the other even starts I would expect you get one thread running to completion before the other starts most of the time.
I have just noticed you lock outside the loop. This will guarantee you also run one thread to completion before the other starts.
This is how you can enforce fair alternation of threads.
public class TestProject implements Runnable {
private final Lock lock;
public TestProject(Lock lock) {
this.lock = lock;
}
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
System.out.print(Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
}
public static void main(String... ignored) {
Lock lock = new ReentrantLock(true);
new Thread(new TestProject(lock), "1").start();
new Thread(new TestProject(lock), "2").start();
}
}
can print
12121212121212121212
Note: if you make the lock non-fair you can get (change the true to false)
11111111112222222222
Note: if you want fair alternation between two tasks, it much simpler to use one thread and a loop.
public static void main(String... ignored) {
for (int i = 0; i < 10; i++) {
// task 1
System.out.print("1");
// task 2
System.out.print("2");
}
}
you can also use join method on myProject1 so that it waits for the other thread to finish
these are the following method that can be used to achieve synchronization among the thread
1). use a static global lock and pass that object variable as argument to the synchronized block
2). use join()
3). create a instance for the Object class and pass that as an argument to the synchronized block like this Object myObject = TestProject.class now pass myObject to the synchronized block
using either of the above ways we can achieve synchronization
Related
Synchronization works well with the below code.
public class Main implements Runnable {
public static void main(String[] args) {
Main m = new Main();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
This question was asked in an interview. I was a bit confused about this so I'm trying to understand why synchronization isn't working with the second code snippet. Can anybody explain me why synchronization won't work with the second code snippet ?
Because synchronization is applied for if you are working on single object.
In first case you have single runnable object of Main i.e. m
In second case you have independent objects of Main.
for(int i=0;i<2;i++){
Thread t = new Thread(new Main()); // independent objects for each thread
t.start();
}
Explaination:
If you see the code you will find below line
synchronized (this) {
this refers to the object itself. So lock is applied based on this object. So in case of multiple Main class object they work independently where as in single object synchronization is applied for that object only.
For more information refer : Intrinsic Locks and Synchronization
Code from the documentation
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) { // lock is acquired using lock1 object
c1++;
}
}
public void inc2() {
synchronized(lock2) { // lock is acquired using lock1 object
c2++;
}
}
}
In this example you can call both the methods inc1() and inc2() using single object at same time because lock is acquired on different objects. This will help you understand it better.
So in your case lock is acquired on this(object itself). So whenever you have multiple object then it will work independently and when you have single object then it will work synchronously.
You are creating two objects here.
synchronized(this) block will synchronize access to the same object if multiple threads try to access it.
synchronized (this)
"this" is the current object instance. In the first example, instance of Main class is created before invoking the thread and same instance is used. Therefore synchronization works.
But in the second example, in each iteration of the loop in main(), new instance of Main is created. synchronized(this) will not work because there are multiple instances of Main class.
in Java syncronized(object) is effectively using object as an exclusive lock for the code block within syncronized. It may be more obvious why the second version doesn't work if we make the lock explicit, and observe how many instances of the lock get created in each case:
public class Lock {
}
public class Main(Lock lock) implements Runnable {
public static void main(String[] args) {
correct()
incorrect()
}
public static void incorrect() {
for (int i = 0; i < 2; i++) {
//New lock created each iteration
Main m = new Main(new Lock())
Thread t = new Thread(m);
t.start();
}
}
public static void correct() {
//One lock used for all iterations
Main m = new Main(new Lock())
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
#Override
public void run() {
synchronized(lock) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
In above example there are 3 threads and 3 Main objects, each thread is taking a lock on different Main object so synchronization will not work.For synchronization to work we should have all threads to take a lock on the single object. Here 3 threads are not taking the lock on a single object but 3 different objects. Each thread is taking a lock on each main object which is not shared among threads. In Thread t = new Thread(m); all threads take a lock on single Main(m) object.
I would have answered that question with a question of my own:
What do you mean, it doesn't work?
The first example serializes the System.out.println() calls and, for the reasons given in several of the other answers here, the second example doesn't serialize the calls, but so what?
System.out is a java.io.PrintWriter, and PrintWriter is inherently thread-safe. Neither of the two examples needs synchronization at all.
I want to run two threads one after the other, without using sleep() or Locks, but a deadlock happens! What's wrong with my code? I used wait() and notifyAll() and an Object object.
public class Test {
public static void main(String[] args) throws InterruptedException {
PrintChar a = new PrintChar('a');
PrintChar b = new PrintChar('b');
Thread ta = new Thread(a);
Thread tb = new Thread(b);
ta.start();
tb.start();
}
}
class PrintChar implements Runnable {
final Object o = new Object();
char ch;
public PrintChar(char a) {
ch = a;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (o) {
System.out.print(ch);
try {
o.wait();
o.notifyAll();
} catch (InterruptedException ex) {
}
}
}
}
}
Running your code, and looking at it, I've found that each thread you generated was generating and synchronizing to its own object, therefore preventing them from notifying each other. I've also found that you wait before notify, so you do not ever get to invoke o.notifyAll(), as o.wait() stops it first.
Change final Object o = new Object() to static final Object o = new Object(), and switch the places of o.wait() and o.notifyAll()
I think the synchronized block is causing the deadlock. Cos it won't let the other thread start until current one finished. You are using wait() method to make the current thread wait. Ok, it will wait but since it is in synchronized block, it will be in the current thread forever never let any other thread to came into existence because of synchronized.
One thing you can do to make the other thread work is using Thread.stop. Try calling stop method in current thread's reference. But I am not sure whether it will let the current thread to start again.
i want to understand this:
String string;
public Test(String string){
this.string = string;
.....
}
public void foo(newObjectPerCall o) {
synchronized (o) {
//each thread can enter here because the object passed is always different
....
synchronized (string) {
// acquire this lock if the String is free.
}
}
}
public synchronized void function() {
}
public static void main(){
Test test = new Test("hello");
for(int i = 0; i < 10;i++){
WorkerThread workerThread = new WorkerThread(test);
workerThread.start();
}
}
thread class
public class WorkerThread extends Thread {
private Test test;
public WorkerThread(Test test) {
this.test = test;
}
#Override
public void run() {
while (true) {
test.foo(new Object());
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.function();
}
}
}
my doubts are:
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes. They will block, waiting to acquire the monitor for string.
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
Yes, it's entirely independent of the other monitors. A synchronized instance method is just equivalent to one whose body is
synchronized (this) {
...
}
If no other thread already owns the monitor for this, the "new" thread can acquire it regardless of what other monitors are owned. But as all your worker threads are using the same instance of Test, only one of them will be able to be "in" function() at a time. That can be at the same time as another thread is executing foo() though.
Sorry I know only the answer only for the first question
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes
I am new to Java. Below is a code as an example of threads and synchronization.
public class A implements Runnable{
public synchronized void run(){
/*
some code here
*/
}
}
public class B {
public static void main(String[] args){
A obj1 = new A();
Thread t = new Thread(obj1);
A obj2 = obj1;
Thread t1 = new Thread(obj2);
t.start();
t1.start();
}
}
Now will this two threads block each other for same lock or will they get two different locks?
Thank you!!
(First, please stick to the Java coding conventions. A class name should always start with a capital letter. No exceptions.)
Only one of the threads will execute the run() method at a time.
The A.run() method is an instance method, and it is declared as synchronized. These two facts mean that it will acquire a lock on this (i.e. the instance of A) before entering the method body, and release it on exiting. In short, run() locks this.
So in your main program you are creating a single A instance and passing it as the target object for two threads. They both need to execute the run() method on the same object, and this cannot happen at the same time ... by the reasoning of the previous paragraph.
This does not necessarily mean that one thread will block the other. It is also possible that the first thread to be started will have completed its run() call before the second thread is ready to try the call. But we can say ... definitively ... that the two threads' calls to run() will NOT overlap in time.
They will block each other, since they're both synchronized on the same object.
For example, this program:
public class Foo
{
public static void main(final String... args)
{
final Runnable r =
new Runnable()
{
public synchronized void run()
{
for(int i = 0; i < 10; ++i)
{
System.out.println(i);
try
{ Thread.sleep(1000L); }
catch(final InterruptedException ie)
{ throw new RuntimeException(ie); }
}
}
};
new Thread(r).start();
new Thread(r).start();
}
}
will print 0 through 9, pausing for a second after number, and then do it again. It will not interlace the two sets of numbers.
Synchronization forces the threads to run in order (block).
Synchronization, by definition, means that a method is run "one at a time". The first thread to be executed (likely "t") will thus complete before the 2nd thread (probably "t1")'s run() method is entered.
To test the synchronization effects:
The best experiment to run will be to fill the run() method with a call to
Thread.sleep(1000);
Then run your code with, and without the "synchronized" keyword, and time the programs execution .
The output of this code is getting intermixing of thread1 and thread0
package oopd;
/**
*
* #author mani deepak
*/
public class Oopd {
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
// TODO code application logic here
Deepak d,d1;
d=new Deepak();
d1=new Deepak();
Thread t,t1;
t=new Thread(d);
t1=new Thread(d1);
t.start();
t1.start();
}
}
class Deepak implements Runnable
{
#Override
public synchronized void run()
{
String s=Thread.currentThread().getName();
for(int i=0;i<10;i++)
{
try
{
Thread.sleep(100);
}
catch(Exception e)
{
}
System.out.println(s+" "+i);
}
}
}
Class ThreadTest extends Thread {
public synchronized void run() {
}
public static void main(String args[])
{
Thread t1=new ThreadTest();
Thread t2=new ThreadTest();
t1.start();
t2.start();
}
}
I want to know in above scenario, how locks obtained and on which object?
Does above scenario valid?
As locks are obtained on a calling object in method synchronisation then in above scenario on which object lock will be obtained. One more question who(or which object) invokes the run method?
Thanks,
-Abhishek
t1 has the lock of the t1 instance.
t2 has the lock of the t2 instance.
But your example doesnt make much sense..
Maybe this example will help you:
public class Test extends Thread {
private String name;
public Test(String name) {
this.name = name;
}
public synchronized void run() {
System.out.println(name);
while(true)
{
// loop endless
}
}
public static void main(String args[])
{
Thread t1= new Test("t1");
Thread t2= new Test("t2");
t1.start();
t2.start();
}
}
The output is:
t1
t2
You have started both the threads, but it depends on JVM which thread it might execute, so depending upon the thread which starts executing will acquire the lock first and the second thread cant be on running state till the first thread stops.
but in your case as both are different thread instances they run parallel, as the lock is acquired at the object level.
Your example doesn't make that much sense, because locks are on a per-instance level, not on a per-class level as you might wanted to use them.
I think you got it wrong a bit. The thread is wrapping up the code that is executing commands. These executions often contain access on other objects. That is the point, where locking comes into the game. Each of these objects have a monitor that can be obtained by threads. However, only one thread can obtain the lock at a time. Thus, other threads are enqueued and can access object as soon as the current holder releases it, trivially by exiting a synchronized code block.
I think you might wanted to do something like this:
class ThreadTest extends Thread
{
private final Foo f;
public ThreadTest(Foo f,int i)
{
super(""+i);
this.f = f;
}
#Override
public void run()
{
f.bar();
}
public static void main(String args[])
{
Foo f = new Foo();
Thread t1 = new ThreadTest(f,1);
Thread t2 = new ThreadTest(f,2);
t1.start();
t2.start();
}
public static class Foo
{
public synchronized void bar()
{
System.out.print("hello form Thread ");
System.out.println(Thread.currentThread().getName());
}
}
}
Formal Definition
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
If what you want is to have only one thread execute at a time (What's the point) then you should call a static method and call that from inside your run(), there is only one static method for all object of a class
How do synchronized static methods work in Java?