The Class X have two methods: test and test1.
I've created two threads: t1 and t2. Thread t1 is accessing test method and t2 is accessing test1 method of same object. When t1 is accessing test method which synchronized it acquires lock on object.
Will t2 be able to access test1 method on same object? Why it is able to access this method if t1 has a lock on it?
If I'm executing the following code
X x = new X();
new MyThread(x).start(); // It execute test() method
new MyThread1(x).start();// It execute test1() method
class X
{
String a = "varsha";
public synchronized void test ()
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
}
public void test1 ()
{
synchronized (a)
{
}
}
}
You have two different locks:
test() locks this;
test1() locks this.a.
The two locks are completely independent and thus the two methods can be called at the same time.
Your code is equivalent to the following:
class X
{
String a = "varsha";
public void test ()
{
synchronized (this)
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void test1 ()
{
synchronized(a)
{
}
}
}
So these methods are synchronizing at different objects (this versus a) and thus can be executed concurrently without locking each other.
Note, that I replaced Thread.currentThread ().sleep (6000) with Thread.sleep (6000) because method sleep is static and thus you don't need any instance of Thread in order to use it.
class X {
String a = "varsha";
public synchronized void test(){
try {
//if you are modifying the instance variable here
// then the test1() synchronized block will
//not be given lock permission to t2 thread
// synchronization is for thread safety.
// In your example you are not modifying the instance variable.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void test1(){
synchronized(a){
}
}
}
Here is whats actually happening.
Every object in Java has a "monitor lock", In this case object "x".
There are two threads (MyThread and MyThread1) trying to acquire this lock in the following sequence -
Imagine there is a queue – MyThread is in front of MyThread1 in this queue because you have started MyThread first followed by MyThread1.
MyThread acquires the lock first and it starts executing, you have invoked the sleep() method on it. This will change the state of MyThread from "execution state" to "waiting state" and then to "ready state", it will release the lock at this moment since it is not in execution state. At this point MyThread1 is ahead in the queue and it acquires the lock and starts executing.
This is in a way similar to the concept of "Context Switch". Refer book - Operating System Internals and Design.
When you mark a method as synchronized, it locks the object for that method; meaning no other thread can access that PARTICULAR method for that object. In your case no other thread can access the test method; but of course test1 method can be accessed.
Related
I'm writing code that requires some synchronization between a few static methods. My goal is to block the execution of any of these methods if one of them executes.
So for example:
public class Foo{
static Object lock = new Object();
static List<SomeObject> listOfObjects = new ArrayList<>() ;
public static void methodA() {
synchronized (lock) {
//Do some stuff
methodB();
}
}
public static List<SomeObject> methodB() {
synchronized (lock) {
//Do some stuff
return listOfObjects;
}
}
}
Now let's assume that the following is executed from somewhere in the code:
Foo.methodA();
Foo.methodB();
My questions are:
Is it actually synchronized? will methodA and methodB won't run concurrently?
If so, will methodA calling methodB create a deadlock?
Answers:
"Is it actually synchronized? will methodA and methodB won't run
concurrently?" - yes, these methods are synchronised. More precisely, code blocks in methods are synchronised.
"If so, will methodA calling methodB create a deadlock?" - no, synchronized keyword is re-entrant in nature it means if a synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock" - from 1
You could improve code a little by providing private and final keywords:
private static final Object lock = new Object();
Also, do not return direct reference to a List you want to protect. Return read only view:
return Collections.unmodifiableList(listOfObjects);
Since now, client has only read only access which protects you from many unexpected situations.
Static versus non-static lock object in synchronized block
Object level lock vs Class level lock in Java
Is it actually synchronized? will methodA and methodB won't run
concurrently?
Yes, this synchronization looks good.
A thread can acquire the same lock multiple times, increasing a lock counter. And after it releases all of them, only then another thread can acquire that lock.
In your code, a thread calling methodA() acquires the lock twice, once in methodA() and then in methodB(). Then it releases them twice (when the synchronized blocks end).
If so, will methodA calling methodB create a deadlock?
No, as explained above, it won't create a deadlock unless you are doing some operations in those methods that can take forever to complete, in which case there will be starvation. If you are not doing any such operation, then I don't think you can get a deadlock when you are using only one lock.
Nope. Method A and method B WILL run concurrently because it's not the methods that are synchronized but the code inside. The code will continue normally with whichever has the lock. Then the other method will finish.
public class Foo1 {
static Object lock = new Object();
static List<Integer> listOfObjects = new ArrayList<>();
public static void main(String[] args) {
new Foo1().start();
}
public void start() {
new Thread(() -> methodA()).start();
// method A has the lock
sleep(1000); // sleep 1 second
// but method B is still entered and prints first
new Thread(() -> methodB()).start();
}
public static void methodA() {
sleep(5000); // sleep 5 seconds
System.out.println("Entering methodA()");
synchronized (lock) {
// Do some stuff
methodB();
}
}
public static List<Integer> methodB() {
System.out.println("Entering methodB()");
synchronized (lock) {
// Do some stuff
return listOfObjects;
}
}
static void sleep(int milli) {
try {
Thread.sleep(milli);
}
catch (InterruptedException ie) {
}
}
}
I tried an interview question with static functions and non static functions as synchronized and one function was non synchronized. As in below code:
public class Resource {
public static synchronized void m1() throws InterruptedException {
System.out.println("Entering m1 method");
Thread.sleep(10000);
System.out.println("Leaving m1 method");
System.out.println();
}
public synchronized void m2() throws InterruptedException {
System.out.println("Entering m2 method");
Thread.sleep(2000);
System.out.println("Leaving m2 method");
System.out.println();
}
public void m3() throws InterruptedException {
System.out.println("Entering m3 method");
Thread.sleep(2000);
System.out.println("Leaving m3 method");
System.out.println();
}
public synchronized void m4() throws InterruptedException {
System.out.println("Entering m4 method");
Thread.sleep(2000);
System.out.println("Leaving m4 method");
System.out.println();
}
}
public class ThreadDemo {
public static void main(String[] args) {
final Resource resource = new Resource();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t3 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t4 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m4();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Here four threads are created.
T1 is calling static synchronized(m1)
T2, T4 are calling synchronized(m2, m4) and
T3 is calling non synnchronized(m3).
It's output is:
Entering m1 method
Entering m3 method
Entering m2 method
Leaving m3 method
Leaving m2 method
Entering m4 method
Leaving m4 method
Leaving m1 method
My question is:
1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?
2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait? If object level lock is working in T2, T4 then in above point why class level locking is not working?
Static method synchronization is an equivalent for
public static void m1() {
synchronize (Resource.class) {
...
}
}
Non-static method synchronization is an equivalent for
public void m2() {
synchronize (this) {
...
}
}
Now if you will have a look where this is using as monitor and where Resource.class object is using as monitor everything should become clear.
A synchronized block in Java is synchronized on some object. All synchronized blocks synchronized on the same object can only have one thread executing inside them at the same time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.
In your case there are two objects. So, this rule is applicable for each object, but not to both.
Regarding your queries:
1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?
in case of static synchronized methods, only one thread acquire lock on these methods among multiple instances of class. If you have two different instances : resource1 and resource2 for Resource class, only one thread will succeed in getting lock on m1().
if resource1.m1() method execution is in progress by one thread, other thread can't execute resource2.m1() unless first thread finish the execution of m1().
Since method m3() is non-synchronized method, any thread can invoke this method without wait and getting lock.
Since both m2() and m4() are synchronized, only one thread will succeed in getting lock on same object ( resource in your example). Other thread has to wait until first thread completes the execution of synchrnozied method and release object level lock.
2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait?If object level lock is working in T2, T4 then in above point why class level locking is not working?
synchronized methods:
Making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
static synchronized methods:
The thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
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
In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time? Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method
The answer depends on the context.
If you are in a synchronized method for an object, then calls by other threads to other methods of the same object instance that are also synchronized are locked. However calls by other threads to non-synchronized methods are not locked – anyone can call them at the same time.
public synchronized void someSynchronizedMethod() {
...
someNonSynchronizedMethod();
...
}
// anyone can call this method even if the someSynchronizedMethod() method has
// been called and the lock has been locked
public void someNonSynchronizedMethod() {
...
}
Also, if you call someSynchronizedMethod() but happen to be within the someNonSynchronizedMethod() method, you still hold the lock. The lock is enabled when you enter a synchronized method (or block) and is disabled when you exit that method. You can call all sorts of other unsynchronized methods and they will still be locked.
But you are asking two different things in your question:
In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time?
Yes. Other methods can access non-synchronized methods.
Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
Uh, yes. Other calls to synchronized methods are locked. But non-synchronized methods are not locked.
Also, remember that if the method is static then the lock is on the Class object in the ClassLoader.
// this locks on the Class object in the ClassLoader
public static synchronized void someStaticMethod() {
If the method is an instance method then the lock is on the instance of the class.
// this locks on the instance object that contains the method
public synchronized void someInstanceMethod() {
There are 2 different locks in those 2 cases.
Lastly, when you are dealing with synchronized instance methods, each instance of the class is what is locked. This means that two threads could be in the same synchronized method at the same time with different instances. But if 2 threads try to operate on synchronized methods on the same instance, one will block until the other one exits the method.
If thread A calls synchronized method M1 which in turn calls unsynchronized method M2, then thread B can still call M2 without blocking.
Synchronized method acquires and releases intrinsic lock on the object on which it is called. This is why it may block. Unsynchronized method doesn't attempt to acquire any lock (unless it is done explicitly in the code).
Thus, if you need to ensure mutual exclusion for M2 as well, you should make it synchronized regardless of whether its callers (like M1) are synchronized or not.
The lock doesn't belong to the thread. The lock actually belongs to the object(or Class in case of Class level lock), and a thread acquires lock on the Object(or Class in case of Class level lock) within a synchronized context.
Now, there is no lock propagation in java as it is discussed above. Here is a small demo:
public class TestThread {
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ThreadCreator1 threadCreator1 = new ThreadCreator1();
ThreadCreator2 threadCreator2 = new ThreadCreator2();
Thread t1 = new Thread(threadCreator1,"Thread 1");
Thread t3 = new Thread(threadCreator1,"Thread 3");
Thread t2 = new Thread(threadCreator2,"Thread 2");
t1.start();
Thread.sleep(2000);
t3.start();
}
}
public class ThreadCreator1 implements Runnable {
private static final Task task= new Task();
private static final Task2 task2= new Task2();
#Override
public void run() {
try {
if(Thread.currentThread().getName().equals("Thread 1"))
task.startTask2(task2);
if(Thread.currentThread().getName().equals("Thread 3"))
task2.startTask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
/**/
}
}
public class Task {
public static final Task task = new Task();
public static List<String> dataList = new ArrayList<String>();
ReentrantLock lock = new ReentrantLock();
public void startTask2(Task2 task2) throws InterruptedException
{
try{
lock.lock();
//new Task2().startTask();
task2.startTask();
}
catch(Exception e)
{
}
finally{
lock.unlock();
}
}
}
public class Task2 {
ReentrantLock lock = new ReentrantLock();
public void startTask() throws InterruptedException
{
try{
//lock.lock();
for(int i =0 ;i< 10;i++)
{
System.out.println(" *** Printing i:"+i+" for:"+Thread.currentThread().getName());
Thread.sleep(1000);
}
}
catch(Exception e)
{
}
/*finally
{
lock.unlock();
}*/
}
}
Just I have used Reentrant lock here.
If the above code is run, then there will be interleaving between thread 1 and thread 3, but if the lock portion of Task2 class is uncommented, then there will be no interleaving and the thread which acquire the lock first will complete fully first, then it will release the lock and then the other thread can carry on.
The lock belongs to the thread, not to the method (or more precisely, its stack frame). It just so happens that if you have a synchronized method, you're guaranteed that the thread will own the lock before the body of the method start, and will release it afterwards.
Another thread can still invoke the second, non-synchronized method. An unsynchronized method can be called by any thread at any time.
class A {
private synchronized f() {
...
...
}
private void g() {
...
...
}
}
If thread T1 is running f() which is synchronized, can thread t2 run g() which is not synchronized at the same point of time, while T1 is still running f()?
Not on the same instance of A. The instance itself is the lock so two execute the two methods at the same time with two threads you would need two instances of A.
Yes. Both methods can execute at the same time on the same instance.
Only f() is synchronized. A thread must acquire the monitor for this.f() to execute f() and only one monitor exists per instance.
g() is not synchronized, no monitor locking is required to run the method, so any thread can execute g() at any time.
"A synchronized method acquires a monitor (§17.1) before it executes."
http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.3.6
No. One call will block until the other completes. The reason for this is that the synchronized keyword on a method expands to synchronize on the current instance of the object. To be more specific, consider this code:
private void synchronized f() {
...
}
The above code is identical in functionality to the following code:
private void f() {
synchronized (this) {
...
}
}
So if you want two methods in an object to be synchronized only to each other, you should create two lock objects. Each method should wrap all of its code inside a synchronized (object) block, one object for each method.
Yes, if T1 and T2 are executing f and g respectively on different instances of A.
If both threads are executing a method on the same instance of A, only one will be able to execute a method at a time. If T1 runs first, it will acquire the lock on the instance of A, and execute method f. Thread T2 will be unable to execute method g until after T1 has finished executing f. Or the opposite could happen: T2 could run g first, and T1 won't be able to run f until after T2 has finished.
In general, two threads can run two methods at the same point in time; however, in your example only one thread might be running f() or g() at any given moment.
Using the synchronized keyword changes thread interactions. Every java object has a lock, an item that only one thread can hold at any given time. Synchronized is a command that directs the threads to acquire the lock before execution of a method and release it afterward. The lock is held during the entire execution of the method.
In your example, only one thread will be executing f() or g() at any given time because the "other" thread will be waiting its turn to grab the lock.
When you have two objects of the same class, you have two locks. That means you could get two threads to run f() and g() simultaneously with the synchronized keywords intact, as the threads will be grabbing locks on different objects. You just can't get threads to execute simultaneously on the same object without removing the synchronized keyword.
The correct answer to this is reassembler's answer.
Run this and you'll see. You can also test using Thread.sleep() instead of an infinite loop by uncommenting/commenting the according sections of the sample.
I apologize if the code doesnt follow best practices, my java is pretty rusty.
package threadtest;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
TestClass tc = new TestClass();
// invokes not sync method
FirstThreadRunnable ftr = new FirstThreadRunnable(tc);
Thread t1 = new Thread(ftr);
// invokes the sync method
SecondThreadRunnable str = new SecondThreadRunnable(tc);
Thread t2 = new Thread(str);
t2.start();
t1.start();
System.in.read();
}
public static class TestClass {
private int callCount = 0;
public void notSynchronizedMethod() {
System.out.println("notSynchronizedMethod says hello!" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());
}
public synchronized void synchronizedMethod() throws InterruptedException {
// Test with the sleep
//System.out.println("entering sync method and pausing from thread: " + Thread.currentThread().getId());
//Thread.sleep(5000); // hold the monitor for 5sec
//System.out.println("exiting sync method" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());
// Test with spinning
System.out.println("MAKE IT SPIN! from thread: " + Thread.currentThread().getId());
boolean spin = true;
while(spin){
}
System.out.println("IT STOPPED SPINNING! from thread: " + Thread.currentThread().getId());
}
}
// invokes the not sync method
public static class FirstThreadRunnable implements Runnable {
TestClass tester = null;
public FirstThreadRunnable(TestClass tester){
this.tester = tester;
}
#Override
public void run() {
for(int i = 0; i < 500; i++){
tester.notSynchronizedMethod();
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
// invokes the sync method
public static class SecondThreadRunnable implements Runnable {
TestClass tester = null;
public SecondThreadRunnable(TestClass tester){
this.tester = tester;
}
#Override
public void run() {
try {
// Test with Sleep()
//for(int i = 0; i < 5; i++){
// tester.synchronizedMethod();
//}
// Test with the spinning
tester.synchronizedMethod();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
for the interest of technicality and pedanticality, yes, both methods could be entered at the same time. one is blocked on synchronized (this), non the less, the method is entered and running, it's first statement is being executed, and the first byte code instruction is carried out.