Determining which thread got the synchronized key - java

I am learning how to work with threads and I ran into this question that with a given code I need to say what whether a certain thread will or will not be able to access a certain function.
Here is the code :
public class InsideClass{}
public class SyncClass{
private InsideClass in1;
private InsideClass in2;
public SyncClass(InsideClass i, InsideClass i2){ in1 = i; in2 = i2; }
public synchronized void func1() { System.out.println("in func1"); }
public void func2() { synchronized(in1) { System.out.println("in func2"); }}
public static synchronized void func3() { System.out.println("in func3"); }
public void func4() { synchronized(in2) { System.out.println("in func4"); }}
public synchronized void func5() {
synchronized(in1) {
synchronized(in2){ System.out.println("in func5"); }}
}}
public class MyThread extends Thread{
private SyncClass sc;
public MyThread(SyncClass s) {
sc = s;
}
public void run(){
sc.func1();
sc.func2();
SyncClass.func3();
sc.func4();
sc.func5();
}
}
public class Sys {
public static void main(String[] args) {
InsideClass in1 = new InsideClass();
InsideClass in2= new InsideClass();
SyncClass s1 = new SyncClass(in1,in2);
SyncClass s2 = new SyncClass(in2,in1);
MyThread t1 = new MyThread(s1);
MyThread t2 = new MyThread(s2);
t1.start();
t2.start();
}
}
The question goes like this, assuming that t1 is preforming task(i) (i=1,2,3,4), will t2 be able to preform func(i+1) or will it get blocked? explain.
I wrote the full question just in case it wasn't clear.
1) Assuming that t1 is preforming func1
a) Will t2 be able to preform func1?
b) Will t2 be able to preform func2?
c) Will t2 be able to preform func3?
d) Will t2 be able to preform func4?
2) Assuming that t1 is preforming func2.
a) Will t2 be able to preform func2?
b) Will t2 be able to preform func3?
c) Will t2 be able to preform func4?
3) Assuming that t1 is preforming func3
a) Will t2 be able to preform func3?
b) Will t2 be able to preform func4?
4) Assuming that t1 is preforming func4
a) Will t2 be able to preform func4?
5) func5 has a unique implementation.
a) How many different locks are cought by this method? Specify who they are.
b) What is the problem that comes up at func5? How would you solve this problem?
I'm not looking for answers to all these questions (even though it would be nice just in case) , but I would like to get an explanation of what is the meaning of an object (in this example in1/in2) inside a synchronized block, when 2 other object are initialized with these objects (s1,s2). If t1 is preforming func1 which is synchronized, how does that effect the attempt to preform func2? (how does the fact that s1 and s2 were initialized with the same objects inflect this issue).
I hope my question was clear enough. Thanks!

A synchronized statement acquires the intrinsic lock of the given object, then performs its body, and then releases the lock.
Object lock = new Object();
synchronized(lock) {
...body...
}
The Java Runtime Environment (JRE) will never allow two threads to acquire the intrinsic lock of the same object at the same time. If one thread acquires the lock, then the second thread to attempt it will be blocked until the first thread releases the lock.
It's important to know that the lock will be released no matter how the thread exits the ...body.... It doesn't matter whether it returns, whether it breaks, whether it simply runs off the end, or whether it throws an exception. The lock will be released in any case.
There's a shortcut way to write a member function whose entire body is synchronized.
This:
class MyClass {
synchronized void foobar(...args...) { ...body... }
}
Means exactly the same as this:
class MyClass {
void foobar(...args...) {
synchronized(this) { ...body... }
}
}
And the same goes for a synchronized static function, except that it synchronizes on the class object instead.
This:
class MyClass {
synchronized static void foobar(...args...) { ...body... }
}
Means exactly the same as this:
class MyClass {
static void foobar(...args...) {
synchronized(MyClass.class) { ...body... }
}
}
It's important to remember the difference between a variable and an object. Two threads can enter a synchronized(foo){...} block at the same time if the variable foo refers to two different objects in the two different contexts. (Think carefully about your in1 and in2 member variables!) Likewise, two different threads can call the same synchronized member function at the same time if the two threads are operating on different objects. (Your example has two different instances of SyncClass!)

The code as stands does not compile.
func5 has three open brackets followed and three close brackets
There is no close bracket to then close the class.
If you have a compiler please compile the code and post again.

Related

Can we have multiple static locks in a class in java

I have multiple methods on which I would like to have static lock so that no two objects can access one method but at the same time different methods do not get locked with those object and can run independently.
class A {
private static final A lock1 = new A();
private static final B lock2 = new B();
public void method1() {
synchronized (lock1) {
// do something
}
}
public void method2() {
synchronized (lock2) {
// do something
}
}
}
Now I want these two methods to be independent of each other when it gets locked but at the same time I want multiple instances of same class to be locked at single method.
How can this be achieved ? By using different class ? Can this be achieved by doing just this ?
First, this is sufficient:
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
Then, with your implementation, method1 and method2 are independent of each other, but only one instance of method1 or method2 can run among all instances of A. If you want to allow different concurrent instances of A so that method1 and method2 of different instances can run concurrently, just declare the locks without static.
In other words: if a1 and a2 are instances of A:
with static locks, if a1.method1 is running, a2.method1 cannot be run by another thread
without static, a1.method1 can be run by only one thread. a1.method1 and a2.method1 can run concurrently.
Locks aren't for methods. Locks are for data. The whole purpose of using a mutex lock is to ensure that different threads will always see a consistent view of some shared data.
Your code example shows two locks, but it doesn't show the data that the locks are supposed to protect. This is better:
class Example {
// R-State variables
private final Object lockR = new Object();
private A a = ...;
private B b = ...;
private C c = ...;
// G-State variables
private final Object lockG = new Object();
private Alpha alpha = ...;
private Beta beta = ...;
private Gamma gamma = ...;
public void methodR() {
synchronized (lockR) {
// do something with a, b, and c.
}
}
public void methodG() {
synchronized (lockG) {
// do something with alpha, beta, and gamma.
}
}
}
My Example class has two independent groups of variables; a, b, and c, and alpha, beta, and gamma. Each independent group has its own independent lock. Any method that accesses any of the "R-State" variables should be synchronized (lockR)..., and likewise for the "G-State" variables and lockG.
If a method needs access to both groups at the same time, then it must lock both locks. But NOTE! That could be a sign that the two groups aren't really independent. If there is any dependency between them, then there really should be just one lock.
Also note, I removed static from the example. That was a purely gratuitous change. I abhor static. You should abhor it too, but that's a different subject that has nothing to do with locking.
Static Lock
If the locked-on object is in a static field, then all instances of that particular Class will share that lock. It means that if one object created from that class is accessing that static lock, another object created from that class can not access that lock.
Non-static Lock
If the class has a lock that is non-static, then each instance will have its own lock, so only calls of the method on the same object will lock each other.
As an example when you use a static lock object:
thread 1 calls obj01.doSomething()
thread 2 calls obj01.doSomething(), will have to wait for thread 1 to finish
thread 3 calls obj02.doSomething(), will also have to wait for thread 1 (and probably 2) to finish.
When you use a non-static lock object:
thread 1 calls obj01.doSomething()
thread 2 calls obj01.doSomething(), will have to wait for thread 1 to finish
thread 3 calls obj02.doSomething(), it can just continue, not minding threads 1 and 2, because this is a new object and it does not depend on the class.
non-static locks are basically object-level Locks. static locks are class level Locks
Object Level Lock
Every object in Java has a unique lock. If a thread wants to execute a synchronized method on a given object, first it has to get a lock of that object. Once the thread got the lock then it is allowed to execute any synchronized method on that object. Once method execution completes automatically thread releases the lock.
public class Example implements Runnable {
#Override
public void run() {
objectLock();
}
public void objectLock() {
System.out.println(Thread.currentThread().getName());
synchronized(this) {
System.out.println("Synchronized block " + Thread.currentThread().getName());
System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Example test1 = new Example();
Thread t1 = new Thread(test1);
Thread t2 = new Thread(test1);
Example test2 = new Example();
Thread t3 = new Thread(test2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
The output will be,
t1
t3
Synchronized block t1
t2
Synchronized block t1 end
Synchronized block t3
Synchronized block t2
Synchronized block t3 end
Synchronized block t2 end
Class Level Locks
Every class in Java has a unique lock which is nothing but a class level lock. If a thread wants to execute a static synchronized method, then the thread requires a class level lock. Once a thread got the class level lock, then it is allowed to execute any static synchronized method of that class. Once method execution completes automatically thread releases the lock.
public class Example implements Runnable {
#Override
public void run() {
classLock();
}
public static void classLock() {
System.out.println(Thread.currentThread().getName());
synchronized(Example.class) {
System.out.println("Synchronized block " + Thread.currentThread().getName());
System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Example test1 = new Example();
Thread t1 = new Thread(test1);
Thread t2 = new Thread(test1);
Example test2 = new Example();
Thread t3 = new Thread(test2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
The output will look like below,
t1
t3
t2
Synchronized block t1
Synchronized block t1 end
Synchronized block t2
Synchronized block t2 end
Synchronized block t3
Synchronized block t3 end
Current Scenario
In here you have two methods and if one method is accessed using one lock and the other is using another lock, with your implementation you can have two objects using each other methods but never the same method.
obj01.method01();
obj02.method02();
this is possible,but not this
obj01.method01();
obj02.method01();
you obj02 has to wait till obj01 finish the method.

In which cases we need to synchronize a method?

Let's say I have the following code in Java
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
}
And I create two threads T1 and T2
Thread T1 = new Thread(c1);
Thread T2 = new Thread(c2);
Where c1 and c2 are two different instances of the class SynchronizedCounter.
It is really needed to synchronize the method increment? Because I know that when we use a synchronized method, the thread hold a lock on the object, in this way other threads cannot acquire the lock on the same object, but threads "associated" with other objects can execute that method without problems. Now, because I have only one thread associated with the object c1, it is anyway needed to use the synchronized method? Also if no other threads associated with the same object exist?
In your specific example, synchronized is not needed because each thread has its own instance of the class, so there is no data "sharing" between them.
If you change your example to:
Thread T1 = new Thread(c);
Thread T2 = new Thread(c);
Then you need to synchronize the method because the ++ operation is not atomic and the instance is shared between threads.
The bottom line is that your class is not thread safe without synchronized. If you never use a single instance across threads it doesn't matter. There are plenty of legitimate use cases for classes which are not thread safe. But as soon as you start sharing them between threads all bets are off (i.e. vicious bugs may appear randomly).
Given code/example does not need synchronization since it is using two distinct instances (and so, variables). But if you have one instance shared between two or more threads, synchronization is needed, despite comments stating otherwise.
Actually it is very simple to create a program to show that behavior:
removed synchronized
added code to call the method from two threads
public class SynchronizedCounter {
private int c = 0;
public void increment() {
c++;
}
public static void main(String... args) throws Exception {
var counter = new SynchronizedCounter();
var t1 = create(100_000, counter);
var t2 = create(100_000, counter);
t1.start();
t2.start();
// wait termination of both threads
t1.join();
t2.join();
System.out.println(counter.c);
}
private static Thread create(int count, SynchronizedCounter counter) {
return new Thread(() -> {
for (var i = 0; i < count; i++) {
counter.increment();
}
System.out.println(counter.c);
});
}
}
Eventually (often?) this will result in weird numbers like:
C:\TMP>java SynchronizedCounter.java
122948
136644
136644
add synchronized and output should always end with 200000:
C:\TMP>java SynchronizedCounter.java
170134
200000
200000
Apparently posted code is not complete: the incremented variable is private and there is no method to retrieve the incremented value. impossible to really know if the method must be synchronized or not.

same variable getting used by different threads is getting updated inside synchronized block

There might be a straightforward for this issue, but I am not understanding the concept here.
I am trying a simple program where I am having 3 threads executing a synchronized block to print letter in an incrementing order.The synchronized block is having lock on the variable(which is a StringBuffer object). Below is the code:
public class SimpleThread extends Thread implements Runnable{
private StringBuffer myBuffer;
public StringBuffer getMyBuffer() {
return myBuffer;
}
public void setMyBuffer(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public SimpleThread(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public void run() {
synchronized (this.myBuffer) {
while((int)(this.myBuffer.charAt(0))!=68) {
for(int i=0;i<3;i++) {
System.out.println(this.myBuffer.charAt(0));
}
char x = this.myBuffer.charAt(0);
this.myBuffer.setCharAt(0, (char) (x+1));
}
//this.myBuffer.setCharAt(0, 'A');
}
}
public static void main(String[] args) {
StringBuffer safeBuffer = new StringBuffer();
safeBuffer.append('A');
SimpleThread one = new SimpleThread(safeBuffer);
one.setName("One");
one.start();
SimpleThread two = new SimpleThread(safeBuffer);
two.setName("Two");
two.start();
SimpleThread three = new SimpleThread(safeBuffer);
three.setName("Three");
three.start();
}
Output for the program is:
A
A
A
B
B
B
C
C
C
It is only printing the value when thread One is executing and for other two threads, the of variable myBuffer is becoming D. What I don't understand is why changing the variable for one object reflect for other objects?
synchronized means only one thread can execute the code block at a time. You might be confusing the wording to think it synchronizes the variable.
When you write synchronized (this.myBuffer), you are telling the program to use myBuffer as a lock when deciding if a thread can execute the following code block.
This means when a thread tries to execute synchronized (this.myBuffer) { } it will attempt to get the lock on myBuffer.
If no other thread has the lock, it will obtain it and execute the
code block.
If another thread has the lock it will wait until the other thread releases the lock (usually by finishing running the code inside the code block).
That means all threads will always take turns executing the contents of synchronized (this.myBuffer) { }.
Since thread "One" is started first, it will get the lock first and finish all the work it has thus incrementing the myBuffer content to D, before handing it over to thread "Two".

Multiple Threads accessing instance method from different Instances should cause a race condition?

I am trying to understand Synchornized in Java.
I understood if I have access a synchronized method on same object from 2 different Threads, only one will be able to access at a time.
But I think if the same method is being called on 2 different instances, Both Objects should be able to access the method parallel. Which would cause race condition if accessing/modifying a static member variable from the method. But I am not able to see the race condition happening in below code.
Could someone please explain whats wrong with the code or my understanding.
For reference code is accessible at : http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
You're right that the race condition exists. But the racy operations are so quick that they're unlikely to happen -- and the synchronized keywords are likely providing synchronization "help" that, while not required by the JLS, hide the races.
If you want to make it a bit more obvious, you can "spell out" the count = count + 1 code and put in a sleep:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
That should show the races more easily. (My handling of the interrupted exception is not good for production code, btw; but it's good enough for small test apps like this.)
The lesson learned here is: race conditions can be really hard to catch through testing, so it's best to really understand the code and prove to yourself that it's right.
Since syncrhonized methods actually synchronize on this different instance methods will lock on different objects and therefore you will get race conditions since they don't block each other.
You probably have to make your own lock object and lock on that.
class MyClass
{
public static int count=0;
//this is what you lock on
private static Object lock = new Object();
public int getCount()
{
synchronized(lock){
System.out.println("Inside getcount()");
return count;
}
}
public void incrementCount()
{
synchronized(lock){
count = count+1;
}
}
//etc
Now when you run your main, this gets printed out:
1000000000
count = 100000000
Here's the relevant section of the Java specification:
"A synchronized method acquires a monitor (ยง17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used."
However I fail to see where the MyClass' instances are actually incrementing "count" so what exactly are you expecting to show as a race condition?
(Taken originally from this answer)

Synchronizing static variables

What I understand by synchronizing static object which is a variable, if one thread is accessing it, other thread can't.
class T3
{
static Integer i = 0;
static void callStatic()
{
synchronized(T3.class)
{
System.out.println(i++);
while(true);
}
}
public void notStatic()
{
System.out.println(i++);
while(true);
}
}
class T2 implements Runnable
{
public void run()
{
System.out.println("calling nonstatic");
new T3().notStatic();
}
}
class T implements Runnable
{
public void run()
{
System.out.println("calling static");
T3.callStatic();
}
}
public class Test
{
public static void main(String[] args)
{
new Thread(new T()).start();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
new Thread(new T2()).start();
}
}
But this demo program has output as :
calling static
0
calling nonstatic
1
Is my understanding wrong? Or am I missing something?
I tried, synchronzing callStatic method, and synchronizing T3.class class object too. But none worked as I thought.
Note : I thought, 1 will not be printed as callStatic has lock on variable i and is in infinite loop.
You don't synchronize on variables, you synchronize on objects.
callStatic synchronizes on 1 and then sets i to 2. If notStatic were to enter a synchronized(i) block at this point, it would synchronize on 2. No other thread has locked 2, so it proceeds.
(Actually, 1 and 2 aren't objects, but Integer.valueOf(1) and Integer.valueOf(2) return objects, and the compiler automatically inserts the Integer.valueOf calls to convert ints to Integers)
In your code, notStatic doesn't actually synchronize at all. It's true that only one thread can be in a synchronized block for a particular object at a particular time, but that has no effect on other threads that are not trying to enter a synchronized block.
Note: This answer relates to the original question, which had synchronized(i), not synchronized(T3.class), in callStatic. The edit really changes the question.
synchronize acts on the object, not the variable/member holding it. There are a couple of important things going on in your code.
synchronize(i) does indeed synchronize access to i provided that the other code trying to use it also synchronizes. It has no effect on code that doesn't synchronize. Suppose Thread A does synchronize(i) and holds it (your infinite loop); then Thread B does System.out.println(i); Thread B can happily read i, there's nothing stopping it. Thread B would have to do
synchronize (i) {
System.out.println(i);
}
...in order to be affected by Thread A's synchronize(i). Your code is (attempting to) synchronized mutation, but not access.
i++; with an Integer is effectively equivalent to i = new Integer(i.intValue() + 1), because Integer is immutable. So it creates a different Integer object and stores that in the i member. So anything synchronizing on the old Integer object has no effect on code synchronizing on the new one. So even if your code were synchronizing both access and mutation, it wouldn't matter, because the synch would be on the old object.
This means that the code in your callStatic is synchronizing on an instance of Integer and then repeated creating a bunch of other instances, which it is not synchronizing on.
Synchronized blocks on static and non static don't block each other. You need to understand how synchronized works for this. Synchronized is done always on an object never on a variable. When you synchronize, thread takes a lock on the object's monitor, the object which you put in the synchronized statement braces.
Synchronized blocks on static references (like in your code) lock on the .class object of your class and not on any instance of that class. So static and non-static synchronized blocks don't block each other.
Now in your code the notStatic method doesn't synchronize on anything where as the callStatic synchronizes on the static i Integer object. So they don't block each other.

Categories

Resources