简体   繁体   中英

What is the use of taking a lock on an object in synchronized block, if it can be accessed in any other method?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM