简体   繁体   中英

Does a synchronized block prevent other thread access to object?

If I do something to a list inside a synchronized block, does it prevent other threads from accessing that list elsewhere?

List<String> myList = new ArrayList<String>();

synchronized {
  mylist.add("Hello");
}

Does this prevent other threads from iterating over myList and removing/adding values?

I'm looking to add/remove values from a list, but at the same time protect it from other threads/methods from iterating over it (as the values in the list might be invalidated)

No, it does not.

The synchronized block only prevents other threads from entering the block (more accurately, it prevents other threads from entering all blocks synchronized on the same object instance - in this case blocks synchronized on this ).

You need to use the instance you want to protect in the synchronized block:

synchronized(myList) {
  mylist.add("Hello");
}

The whole area is quite well explained in the Java tutorial:

http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Yes, but only if all other accesses to myList are protected by synchronized blocks on the same object . The code sample you posted is missing an object on which you synchronize (ie, the object whose mutex lock you acquire). If you synchronize on different objects or fail to synchronize at all in one instance, then other threads may very well access the list concurrently. Therefore, you must ensure that all threads have to enter a synchronized block on the same object (eg, using synchronized (myList) { ... } consistently) before accessing the list. In fact, there is already a factory method that will wrap each method of your list with synchronized methods for you: Collections.synchronizedList .

However, you can certainly use Collections.synchronizedList to wrap your list so that all of its methods are individually synchronized, but that doesn't necessarily mean that your application's invariants are maintained. Individually marking each method of the list as synchronized will ensure that the list's internal state remains consistent, but your application may wish for more, in which case you will need to write some more complex synchronization logic or see if you can take advantage of the Concurrency API (highly recommended).

here the sychronized makes sure that only one thread is adding Hello to the myList at a time...

to be more specific about synchronizing wrt objects yu can use

synchronized( myList ) //object name
{
    //other code
}

vinod

From my limited understanding of concurrency control in Java I would say that it is unlikely that the code above would present the behaviour you are looking for.

The synchronised block would use the lock of whatever object you are calling said code in, which would in no way stop any other code from accessing that list unless said other code was also synchronised using the same lock object.

I have no idea if this would work, or if its in any way advised, but I think that:

List myList = new ArrayList();

synchronized(myList) { mylist.add("Hello"); }

would give the behaviour you describe, by synchronizing on the lock object of the list itself.

However, the Java documentation recommends this way to get a synchronized list:

List list = Collections.synchronizedList(new ArrayList(...));

See: http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html

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