开发者

Threads and Synchronization

I have a little difficulty in understanding the concept of private locks:

public class MyObject {
  private final Object lock = new Object(); // private final lock object

  public void mymethod() {
    synchronize开发者_JS百科d (lock) { // Locks on the private Object
      // ...
    }
  }
}

In the code above, lock is acquired on a different object but the code in the current object is guarded by synchronised block. Now, apart from the lock object in the code above, it could be any other object too. I find it difficult to understand how the lock on another object is related to the synchronised keyword in the current object. IMO, it may lead to some malicious code to lock any object. What is the basis of allowing locks on other objects.


Well you could, for example, have an object that manages two lists.

If its possible for thread A to alter list 1 while thread B alters list 2 then you'd use distinct locks, rather than synchronizing on the owning object.

Essentially explicit locks allow for finer grained control of behavior.


IMO, it may lead to some malicious code to lock any object.

This is the crux of the issue, actually.

With a separate lock object as shown (crucially, with private access) then only code in the MyObject class will be able to acquire a lock on that monitor - so you can see all of the code that might take part in locking situations involving this class.

Going to the other extreme, if you acquire a lock on e.g. a constant String, then any code, anywhere in the same JVM that locks on the same String will contend with your class - which is almost certainly not intended and will be very hard to track down.

Basically - if you lock on a non-private object, that then becomes part of your public interface, effectively. Sometimes this is intended (e.g. for the Collections.synchronizedFoo objects, they declare that one can synchronize on the object itself in order to coarsen your lock). Often it is not and is merely an oversight.

You should keep your lock monitors private, for the same reason you keep private member variables private - to prevent other code messing with things that they shouldn't. And this is basically never private.


You're right, the code you provided could lock on any object. However, it didn't. It locked on a private instance field--a field which only that instance can access. That means that no other code can possibly lock on that object. You didn't, in this case, lock on some other object because if some other code locked on it, then you'd have to wait for it (and it may never be released).

"Malicious" code could lock on any object, but it only hurts other code if that other code attempts to lock on the same object. My creating your own private object to lock on, you protect yourself from locks by other code.


synchronized is actually effective for multithreaded environment. This method is to allow concurrency in your system.

When an object is synchronized, the first thread that "touched" the object puts a lock on that object until that thread that is using the locked object finished using the object and releases it. It prevents many threads to change the same object concurrently.


Locks are always on objects.

purpose of syncronized block is to guard objects (one associated with block) with locks, So this means only thread which has lock for object can enter this block.

There is nothing wrong with it, There can be situation in code where you don't need to synchronize complete method but just few lines of code.

One use of synchronization block is in situation when state of object (and other objects related to it) needs to changed in multi threaded env, But the Class of this object doesn't have synchronized methods to alter state of object. In such situation synchronization is achieved using such block.


Locks should be private iff there will be no reason for any lock related to your class to be held while no thread is actually running code in your class (or code called from code in your class). If you need to e.g. allow someone to maintain exclusive control over your object between operations, you'll have to expose a lock. This opens up many potential issues, including deadlock, so it's generally best if you can design your interfaces and contracts so as to render such extended locking unnecessary.

BTW, note that performing callbacks while holding a lock is slightly less dangerous than exposing a lock, but only slightly. You would eliminate the danger that a caller might acquire a lock and simply forget about it, but the danger of deadlock would still remain.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜