I have a quick question about Java synchronization.
Please assume the following code:
public class Test {
private String address;
private int age;
public synchronized setAddress(String a) {
address = a;
}
public synchronized setAge(int a) {
age = a;
}
public synchronized void start() {
...
listener = new Thread(new Runnable(){
public void run() {
...
setAge(10);
...
synchronized(Test.this) {
address = null;
}
}
}
}
}
I am a little bit unsure about Java synchronization when synchronized method or synchronized block is called inside another thread.
Assume the thread running class Test as A, and
the listener thread B.
Then if I execute the code above, does it guarantee that synchronized method calls and synchronized block are synchronized with the A (the thread running Test class) ?
Thank you for reading.
No,
The synchronized methods are locking the Test instance, while the synchronized block is locking the Test class object.
See Java synchronized static methods: lock on object or class and Java Synchronized Block for .class
Related
I have a class like this one:
public class IClass{
public void draw(){...}; //is called periodically by the rendering thread
public void foo(){...}; //is called asynchronously from another Thread(it could be an onTouchEvent() method for example)
}
I want the foo() method to wait until the draw method is finished and vice versa. How can I do this in Java?
regards
Make the methods synchronized.
public synchronized void draw() { System.out.println("draw"); }
public synchronized void foo() { System.out.println("foo"); }
Or synchronize on the same object.
private static final Object syncObj = new Object();
public void draw() {
synchronized (syncObj) {
System.out.println("draw");
}
}
public void foo() {
synchronized (syncObj) {
System.out.println("foo");
}
}
Putting synchronized on a method means the thread has to acquire the lock on the object instance before entering that method, so if you have two different methods marked synchronized the threads entering them will be contending for the same lock, and once one thread gets the lock all other threads are shut out of all methods that synchronize on that same lock. So in order for the two methods to run concurrently they would have to use different locks, like this:
public class IClass {
private final Object lockDraw = new Object();
private final Object lockFoo = new Object();
public void draw() {
synchronized(lockDraw) {
//method draw
}
}
public void foo() {
synchronized(lockFoo) {
//method foo
}
}
}
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).
I have few queries regarding Synchronization in Java. I have read a lot of content online and have feeded myself with lot of information and so with multiple doubts.
I will list down my queries, so please anyone help me out with my doubts.
Object level synchronization :
1) For following code sample.
public synchronized void a(){
//todo
}
}
What will be the LOCK used. Will it automatically be lock on "this" as we have it in case below sample code ?
public void a(){
synchronized (this) {
//TODO
}
}
2) We have multiple methods code blocks locking on "this".
public void a(){
synchronized (this) {
//TODO
}
}
public synchronized void b(){
synchronized (this) {
//TODO
}
}
So does this means that if code block of b() is locked, then any other thread wont be able to access a() as well at the same time as they have a lock on the object(this)?
Class level synchronization :
3) For the following code
public static void c(){
synchronized (Main.class) {
//todo
}
}public static void d(){
synchronized (Main.class) {
//todo
}
}public static void e(){
//no syncronization here
}
Question 1 : IF c() is locked will any other thread be able to access d() which has synchronized block as well ?
Question 2: If c() is under lock, will any other thread will be able to access e() which is a non synchronized method ?
Yes "this" is the lock
Yes
The lock is on Main.class so if the lock in c is already acquired d can't be accessed by another thread.
in point 3. e() can always be accessed by multiple threads no matter what since its not synchronized.
Hope that helps :)
public synchronized int getCountOne() {
return count++;
}
Like in above code synchronizing on the method is functionally equivalent to having a synchronized (this) block around the body of the method. The object "this" doesn't become locked, rather the object "this" is used as the mutex and the body is prevented from executing concurrently with other code sections also synchronized on "this."
On similar grounds what is used as a mutex when we acquire a class level lock.As in if we have a function
public static synchronized int getCountTwo() {
return count++;
}
obviously two threads can simultaneously obtain locks on getCountOne(object level lock) and getCountTwo(class level lock). So as getCountOne is analogous to
public int getCountOne() {
synchronized(this) {
return count++;
}
}
is there an equivalent of getCountTwo? If no what criteria is used to obtain a Class level lock?
On similar grounds what is used as a mutex when we acquire a class level lock
The class object itself will be used as mutex. The equivalent synchronized block for your static synchronized method will look like:
public static int getCountTwo() {
synchronized(ClassName.class) {
return count++;
}
}
ClassName is the name of the class containing that method.
See JLS Section §8.4.3.6:
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.
Emphasis mine.
Object level locking:
Object level locking is mechanism when you want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe. This can be done as below :
public class DemoClass
{
public synchronized void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
Class level locking:
Class level locking prevents multiple threads to enter in synchronized block in any of all available instances on runtime. This means if in runtime there are 100 instances of DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads. This should always be done to make static data thread safe.
public class DemoClass
{
public synchronized static void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final static Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}
What would be the behaviour of the following program where static synchronized method and instance synchronized method is trying to access static field of same class in different threads? Will any thread get blocked? Its very confusing.
class MyClass
{
public static int i = 5;
public synchronized void m1()
{
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
public static synchronized void m3()
{
//T2 will be able to call this method on same object lock while it is using
//static field i???
System.out.println(i);//uses static field i of MyClass
}
}
Synchronized instance methods are equivalent of
public void m1() {
synchronized(this) {
...
}
}
(well, they are not exactly the same, but the answer to your question does not suffer from that difference).
Synchronized static methods are synchronized on the class:
public void m2() {
synchronized(MyClass.class) {
...
}
}
As you can see, two block are synchronized on difference objects: m1 is synchronized on the instance it is called on, and m2 is synchronized on the instance of Class<MyClass> which represents your class in JVM. So those two methods can be called without blocking each other.
You are always synchronizing on an object.
Funciton m1 synchronizes on an instance of an object on which it is called.
Function m3 synchronizes on the class itself.
m1 could be written as:
public void m1()
{
synchronized(this) {
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
}
Therefore you are synchronizing on two different objects and these two methods can acces any global variable concurrently.
Your sample code looks good.
Best way to assure synchronization of static variables according to me is. As lock object is not accessible outside your Class. See below.
public class MyClass
{
private static int i = 0;
private static final Object lockObject = new Object();
public void m1() {
synchronized (lockObject ) {
//Use you static var
}
}
public void m3() {
synchronized (lockObject ) {
//Use you static var
}
}
}
The method m1 and m3 can be executed independently.
Because as you already said static synchronized is on the object. Therefore the same as synchronize(MyClass.class).
synchronized are instance wide usable. So it is only blocked for the instances. It would be the same as using:
MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}
Java does not have any synchronization controls that relate to accessing static fields.
If you make your methods empty, the synchronization will be exactly the same.
Specifically, as long as any thread is executing any synchronized static method in that type, all other threads that call synchronized static methods will wait for them to finish, so that at most one synchronized static method will be executing at once.
I have a method with a synchronization statement on an "non-this" object
class Some_Class {
public A s = new A();
public void method_A() {
synchronized(s) {
....
}
}
}
Can I instead extend class A and synchronize as follows:
class B extends A {
public A a;
public B(A a) {
this.a = a;
}
public synchronized void some_m() {
...
}
}
class Some_Class {
public A s = new A();
public void method_A() {
B b = new B(s);
b.some_m();
}
}
Are these two synchronizations equivalent?
No, they're not equivalent. This method here:
public synchronized void some_m() {
...
}
Does the same as this one:
public void some_m() {
synchronized(this) {
...
}
}
Or in other words
Your first code option synchronises on an instance of A in Some_Class (a class member, visible to everyone).
Your second code option synchronises on the instance of B within Some_Class.method_A() (a local variable, invisible to the outside of that method)
No, they are not equivalent. In second case you actually don't have synchronization at all. Because some_m method synchronized on instance of B. So you create local instance of B and call method on it. This method is synchronized only on this local instance of B and other threads don't care about it and can do whatever they want with s because it's not synchronized.
Can you describe what you want to achieve?
Synchronized block synchronizes the whole object while synchronized method synchronizes just that method. In the second case, some thread can still access other non-synchronized methods of the object.