Here my code is:
public class Child extends Thread {
public void run(){
synchronized (this)
{
for(int i=1;i<=5;i++)
{
System.out.println("child thread");
}
}
}
}
class ThreadTest{
public static void main(String []a) {
Child child=new Child();
**child.start();**
synchronized (child)
{
for(int i=1;i<=5;i++)
{
System.out.println("parent thread");
}
}
}
}
It first prints "parent thread" after that it prints "child thread" but my doubt is, when we invoke start() method there is a chance to invoke child thread before main thread. But it always prints "parent thread" after that "child thread". can any one explain?
Somewhere inside the child.start() call (i.e., before start() returns) the new thread is created, and it becomes eligible to run. From that point on, it's a race to see which thread will reach it's respective synchronized(...) block first. There's no way to know which one will win, and there's no reason to think that it will be the same winner every time.
P.S.: Synchronizing on a Thread object is not a good idea. The Thread class also synchronizes on Thread instances for its own purposes, and there is a risk that your use of the Thread object as a lock could interfere with the Thread class's use of it.
A good habit is to synchronize on a private object.
class MyClass {
private final Object myLock = new Object();
SomeType someMethod(...) {
synchronized(myLock) {
....
}
}
}
Related
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
Here I have an object with 2 threads and providing lock on object by print() but after some loop it losing lock and execute the second thread and it will change the value of breakLoop and first thread will be terminate.
public class ThreadLock {
public static void main(String[] args) {
Entity entity=new Entity();
RunnableClass runnable = new RunnableClass(entity);
Thread threadClass= new Thread(runnable);
Thread threadClass2= new Thread(runnable);
threadClass.setName("First Thread");
threadClass2.setName("Second Thread");
threadClass.start();
threadClass2.start();
}
}
class RunnableClass implements Runnable{
Entity entity;
public RunnableClass(Entity entity) {
this.entity=entity;
}
public void run(){
if(Thread.currentThread().getName().equalsIgnoreCase("First Thread"))
entity.print();
else{
entity.print("");
}
}
}
class Entity{
public void print(String str){
System.out.println("Non sysncronized method accessed by "+Thread.currentThread().getName());
breakLoop=false;
}
boolean breakLoop=true;
//lock will work for same object
public synchronized void print(){
System.out.println("Lock aquired by : "+Thread.currentThread().getName());
while (breakLoop) {
System.out.println("hhhhhhhhhhhhhh");
}
System.out.println("Lock released by : "+Thread.currentThread().getName());
}
}
The first thread having the lock doesn't stop the second thread from calling the Entity.print(String) method, because that method doesn't try to acquire the lock. Calling print(String) sets the breakLoop flag to false.
(When the flag value becomes visible to the other thread is not well-defined due to memory visibility issues --it would be better to make the breakLoop instance variable volatile-- but that doesn't necessarily mean the second thread will never see the change to the instance variable. Memory visibility issues are more apparent on some platforms than others.)
If you change the print(String) method to be synchronized, it will hang waiting for the first thread to finish.
Was wondering if someone could help clear this up for me. (Student)
Say we have two threads, "Thread1" & "Thread2". If Thread1 is executing in method 1 can Thread2 then execute in method2?
void method1() {
synchronized (this) {
}
}
void method2() {
synchronized (this) {
}
}
I'm either thinking yes, Thread2 can enter as "this" is just the instance of that method or no because "this" is the instance of that class and Thread1 holds onto it.
There isn't a monitor associated with a specific method - there's a monitor associated with an object. So if you're trying to synchronize on the same object in both methods, the second thread will block until the first thread releases the monitor.
(Personally I don't like synchronizing on this anyway - I synchronize on a reference to an object that only my class has access to. But that's a different matter.)
Everybody jumped on an obvious answer here. It is a correct answer, but it is not the only correct answer.
The rule is, two threads can not both synchronize on the same object at the same time. But does this refer to the same object in both method calls? We can't tell because you have not shown us the calls. Consider this example:
class Demo {
synchronized void method1() {
...do something...
}
synchronized void method2() {
...do something else...
}
static void caseA() {
final Demo demo = new Demo();
new Thread(new Runnable(){
#Override
public void run() {
demo.method1();
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
demo.method2();
}
}).start();
}
static void caseB() {
final Demo demo1 = new Demo();
final Demo demo2 = new Demo();
new Thread(new Runnable(){
#Override
public void run() {
demo1.method1();
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
demo2.method2();
}
}).start();
}
}
In caseA(), the calls to demo.method1() and demo.method2() can not overlap because both calls synchronize on the same object, but in caseB() the two calls are synchronized on two different instances of the Demo class. In caseB() the method1() call and the method2() call can overlap.
You are using this for synchronization, which is an instance of an object. Synchronization always works on some particular instance of object and only one thread at any given time can acquire lock of (synchronize on) a single instance used for synchronization and.
Both threads can access the methods only if they use separate instances of the object containing those methods.
The second thread will block until the monitor is released by the first as synchronization is done on the same object for both methods.
You'd better synchronized on the static object you want to lock.
Here, your method 2 will be executed by thread 2, but the content of the synchronized block in method 2 will not be executed unless thread 1 has unlock this. Since your synchronization is on a block, and not on a method, the method is not synchronized, but the block is.
If you have a static member on which you want work in the synchronized, use it like:
private static List<Object> myList;
void method1() {
synchronized (myList) {
// do something on myList
}
}
void method2() {
synchronized (myList) {
// do something on myList
}
}
No Thread2 will have to wait until Thread1 is finished executing the code in synchronised block. This is because you are using the same object (this) to lock. If you did something like this:
Object lock1 = new Object();
Object lock2 = new Object();
void method1() {
synchronized (lock1) { }
}
void method2() {
synchronized (lock2) { }
}
Then you would be able to have Thread1 execute method1 and Thread2 execute method2.
I tried some code to justify the reliability of synchronized block locking mechanism. Consider my sample code
My clocking object.
public class MyLock {
final static Object lock=new Object();
}
Class with synchronized blocks
public class Sample {
public void a(String input) {
System.out.println(input+" method a");
synchronized (lock) {
System.out.println("inside synchronized block in a");
try {
System.out.println("waiting in a");
Thread.sleep(5000);
System.out.println("calling b() from a");
new Sample().b("call from a");
System.out.println("waiting again in a");
Thread.sleep(5000);
System.out.println("Running again a");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void b(String input) {
System.out.println(input+" method b");
synchronized (lock) {
System.out.println("bbb " + input);
}
}
}
Test1 class
public class Test1 implements Runnable{
public static void main(String[] args) {
new Thread(new Test1()).start();
new Thread(new Test2()).start();
}
#Override
public void run() {
new Sample().a("call from main");
}
}
Test2 class
public class Test2 implements Runnable {
#Override
public void run() {
new Sample().b("call from main");
}
}
I just did this because I thought there will be a dead lock scenario if same thread witch holding the lock is going to access another method witch locked using same lock. Now consider the out put
call from main method a
call from main method b
inside synchronized block in a
waiting in a
calling b() from a // i thought this will cause a dead lock
call from a method b
bbb call from a
waiting again in a
Running again a
bbb call from main
Now you can see there is no such issue. My question is how Java manage this situation?
synchronized block is Reentrant
By default the lock (mutex to be precise) used in synchronized block is Reentrant, which means if the same thread tries to acquire the same lock again it will not have to wait and will immediately enter the critical block as it already owns that lock.
Where is Reentrancy useful?
Simple answer is Recursion.
Consider the scenario of recursion on a synchronized method,
int synchronized method(int param){
//... some logic
method(param - 1);
}
In this example you would not want the same thread to be blocked for the same lock, as it will never be able to proceed.
Deadlock occurs in this scenario:
Thread A acquires lock A
Thread B acquires lock B
Thread A tries to acquire lock B
Thread B tries to acquire lock A
Now in this situation no one will be able to proceed and hence deadlock. But in your scenario there is only one lock, so the other thread will just wait for the first thread to leave the lock and then continue.
Since your lock object is static it is shared among threads. Once thread A has acquired the lock, and when thread B enters method B of sample class it tries to acquire the same lock Which is owned by thread A. So there is no chance of deadlock.
Problem could have been where thread A tries to acuire the lock it already holds in method B, but this hasnt happened in your case as synchnorized block itself is reenterant but if you would have implemented your own lock class and if you wouldnt have cjecked for renterency, there would have been a dead lock.
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?