If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
public static void main(String[] args) {
A a = new A();
new Thread(new MyRunnable(a), "T1").start();
new Thread(new MyRunnable(a), "T2").start();
}
static class MyRunnable implements Runnable {
A a;
public MyRunnable(A a) {
super();
this.a = a;
}
@Override
public void run() {
while (true) {
if ("T1".equals(Thread.currentThread().getName())) {
a.m1();
} else {
a.m2();
}
}
}
}
static class A {
StringBuilder abc = new StringBuilder("fdfd");
public void m1() {
synchronized (abc)
{
System.out.println("abc locked : " + abc);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();}
System.out.println("abc released: " + abc);
}
}
public void m2() {
System.out
.println(Thread.currentThread().getName() + " running");
System.out.println("trying to access abc");
abc.append("A");
System.out.println("abc accessed");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
}
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
OUTPUT:
abc locked : fdfd
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc released: fdfdAA
abc accessed
abc locked : fdfdAAA
T2 running
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
Uh yes. I think you need to do some reading about what synchronized
does. See the Java tutorial . It does not "lock" an object as in restrict other threads from operating on it. What it does is provide mutex for the surrounded block of code for threads that lock on the same object instance . The fields in an object are perfectly able to be mutated both inside or outside the synchronized
block.
It is always a good idea to synchronize on a constant object so I tend to do something like:
private final Object lock = new Object();
...
synchronized (lock) {
// only one thread allowed inside this block at a time
}
If multiple threads are accessing some sort of thread-unsafe object, I will synchronize on that object and do the operations on the object inside the synchronized
block:
private final SomeUnsafeObject someObject = ...;
...
synchronized (someObject) {
// only one thread allowed inside this block at a time
someObject.someUnsafeMethodCall(...);
}
// no accesses (read or write) outside of the synchronized block
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
No, there is no implicit blocking of the object being changed. If you only access the object's fields inside of the synchronized
block then you would have accomplished what you want.
public void m2() {
...
abc.append("A");
Right, since you are not inside of a synchronized (abc)
block here, there is nothing that stops the thread from calling abc.append(...)
.
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
Synchronization allows you to control access to a block of code to one thread at a time based on the lock object (or the monitor on that object to be precise). It also allows you to do lock.wait(...)
and lock.notify(...)
to control the threads operation and block/release them as well.
Synchronization also puts up memory barriers so that a thread will see changes stored to central memory when it enters a synchronized
block and will see it's changes written to central memory when it leaves. Without these memory barriers, if other threads access the StringBuilder
without synchronization then they may seem some partially updated portion of that class which can cause NPEs or other failures.
A thread will only have to wait to access a locked code region, if that lock is held by another thread. However, it doesn't have to wait if it doesn't need a lock, ie, your StringBuilder
instance is only safe if every access is surrounded by a synchronized
block locking on the same lock.
In your case, since access to abc
in method m2()
is not in synchronized block, a thread doesn't need a lock, and hence can access it.
When you are synchronizing on a Lock object
the lock object has to be accessible by all threads, so either use a static object
or a field
belonging to the calling code.
Then you code will work to have only only one thread at a time accessing a certain block(s) of code. It will not prevent you acting in that code in anyway that you wish, but only one Thread can do it at one time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.