An object has two synchronized list attributes (listA and listB) and a method called add(...) which adds an element into these two lists. My question is: should this method be synchronized if it is called from differnt threads?
can problems occur when the method SwingUtilities.invokeLater is used inside synchronozed methods?
when using synchronized(this){..code...}, is in this case only the code-block or all methods of the object (this) blocked when a thread access the code-block?
Actually synchronized methods are the same as synchronized(this){} because "this" refers to the object and this one will provide the lock. If you use any of these synchronizations and one thread calls a synchronized method, the other threads cannot access all synchronized methods of the object. if you want to avoid this, create a new variable to provide the lock instead of synchronizing the method. For instance
public void add(String s)
{
private Object block = new Object();
synchronized(block)
{
listA.add(s);
listB.add(s);
}
}
public int count()
{
return listA.size(); //returns the most recent listA update size
// method can be accessed while another thread adds elements to listA
}
An object has two synchronized list attributes (listA and listB) and a
method called add(...) which adds an element into these two lists. My
question is: should this method be synchronized if it is called from
differnt threads?
That depends. If you want the order of the elements in listA and listB to be the same, then yes, you should synchronize when you're adding to both lists. Otherwise, if would be possible that you get things in this order:
Thread A adds element to listA
Thread B adds element to listA
Thread B adds element to listB
Thread A adds element to listB
-
can problems occur when the method SwingUtilities.invokeLater is used
inside synchronozed methods?
No, there's no problem with that. I don't really see what problem you think that you could get.
when using synchronized(this){..code...}, is in this case only the
code-block or all methods of the object (this) blocked when a thread
access the code-block?
It blocks all non-static methods that are synchronized (because that means the same as synchronized (this) and all code blocks that use synchronized (this).
In addition, it blocks any code in other classes that synchronizes on the same object.
Static methods and non-synchronized methods do not block while you are inside synchronized (this).
Related
Consider this code:
public synchronized void onSignalsTimeout(List<SignalSpec> specs) {
if (specs != null && specs.size() > 0) {
for (SignalSpec spec : specs) {
ParsedCANSignal timeoutedSignal = new ParsedCANSignal();
SignalsProvider.getInstance().setSignal(spec.name, spec.parent.parent.channel, timeoutedSignal);
}
}
}
I've got simple question:
When Thread 1 calls onSignalsTimeout method, can Thread 2 access objects that are accessed in that method?
Can't find anywhere if 'synchronized' locks only access to this method or access to all objects used in this method.
First of all, forget about synchronized methods. A so-called synchronized method...
synchronized AnyType foobar(...) {
doSomething();
}
Is nothing but a shortcut way of writing this:
AnyType foobar(...) {
synchronized(this) {
doSomething();
}
}
There is nothing special about the method in either case. What is special is the synchronized block, and what a synchronized block does is very simple. When the JVM executes this:
synchronized(foo) {
doSomething();
}
It first evaluates the expression foo. The result must be an object reference. Then it locks the object, performs the body of the synchronized block, and then it unlocks the object.
But what does locked mean? It may mean less than you think. It does not prevent other threads from using the object. It doesn't prevent them from accessing the object's fields or, from updating its fields. The only thing that locking an object prevents is, it prevents other threads from locking the same object at the same time.
If thread A tries to enter synchronized(foo) {...} while thread B already has foo locked (either in the same synchronized block, or in a different one), then thread A will be forced to wait until thread B releases the lock.
You use synchronized blocks to protect data.
Suppose your program has some collection of objects that can be in different states. Suppose that some states make sense, but there are other states that don't make sense—invalid states.
Suppose that it is not possible for a thread to change the data from one valid state to another valid state without temporarily creating an invalid state.
If you put the code that changes the state in a synchronized(foo) block, and you put every block of code that can see the state into a synchronized block that locks the same object, foo, then you will prevent other threads from seeing the temporary invalid state.
Yes, other threads can access the objects used in the method; the synchronized keyword guarantees that no more than one thread at the time can execute the code of the method.
From https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing
a synchronized method for an object, all other threads that invoke
synchronized methods for the same object block (suspend execution)
until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent
invocation of a synchronized method for the same object. This
guarantees that changes to the state of the object are visible to all
threads. Note that constructors cannot be synchronized — using the
synchronized keyword with a constructor is a syntax error.
Synchronizing constructors doesn't make sense, because only the thread
that creates an object should have access to it while it is being
constructed.
In this context, synchronized simultaneously locks this method and any other method similarly marked as synchronized in your class.
I am attempting to understand the difference between the Vector and ArrayList classes in terms of thread-safety. Vector is supposedly internally synchronized. Is it synchronized by each element, or as a whole? (I could imagine the case where multiple threads could access the vector at the same time, but multiple threads could not access the same element at the same time). If you look at the code below, getAo() is not equivalent to getV() because the synchronized keyword when used in a method signature synchronizes on the containing class object (an instance of VectorVsArrayList) to my knowledge. HOWEVER, is getAoSync() equivalent to getV()? By equivalent, I mean does the ao instance variable start behaving like a Vector object in terms of synchronization as long as all access to it goes through the getter method?
public class VectorVsArrayList {
private ArrayList<?> ao = null;
private Vector<?> v = null;
public ArrayList<?> getAoSync(){
synchronized(ao){
return ao;
}
}
public synchronized ArrayList<?> getAo() {
return ao;
}
public Vector<?> getV() {
return v;
}
}
They aren't equivalent. What you're looking for is Collections.synchronizedList which can "wrap around" any list, including ArrayList.
Short answer: No, it's not equivalent.
When you use synchronized around that return ao;, the ArrayList is only synchronized during the return instruction. This means that 2 threads cannot get the object at the exact same time, but once they have got it, they can modify it at the same time.
If 2 threads execute this code, the add() is not thread safe:
ArrayList<?> list = getAo(); // cannot be executed concurrently
list.add(something); // CAN be executed concurrently
Side note: don't use Vectors, take a look at this post to know why.
to do the equivalent of Vector you should protect any access to any element in the collection, the method getAo simply sychronize the access to the array list.
If two threads call getAo and after each thread call "add" method over this arraylist then you could have a multi thread problem (because "add" is not synch").
I recommend you to check the atomic classes like CopyOnWriteArrayList:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
Why is this code not thread-safe even though we are using synchronized method and hence obtaining a lock on Helper object?
class ListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
Because the list is unlocked when contains returns, and then locked again when add is called. Something else could add the same element between the two.
If you mean to only use the list from within the helper object, it should be declared private; if you do this, the code will be thread safe, as long as all manipulations of the list go through methods that are synchronized in the helper object. It's also worth noting that as long as this is the case, you don't need to be using a Collections.synchronizedList as you're providing all necessary synchronization in your own code.
Alternatively, if you want to allow the list to be public, you need to synchronize your access on the list, rather than on your helper object. The following would be thread safe:
class ListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
}
The difference is that it is using the same lock as the other methods of the list, rather than a different one.
This code is not thread safe only because list is public.
If the list instance is private, and referenced nowhere else, this code is threadsafe. Else it is not threadsafe as multiple threads could be manipulating the list simultaneously.
If the list is not referenced elsewhere, you need not declare it as a synchronized list through the collections class, as long as all list manipulation occurs through synchronized methods and a reference to that list is never returned to anything.
When you mark a method synchronized, all threads calling that method are synchronized with the object instance said method is defined in. This is why if ListHelper internal list instance is not referenced elsewhere, and all methods are synchronized, your code would be threadsafe.
A major component of thread safety concerns more than only mutual exclusion. It is quite possible to complete an atomic update of an object's state, i.e. to effect a state transition that leaves an object in a valid state with its invariants intact, but to still leave the object vulnerable if its references are still published to untrustworthy or incompletely debugged clients.
In the example you post:
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
The code is thread safe, as W.M. pointed out. But we have no assurances about x itself and where it may have references still held by other code. If such references did exist, another thread can modify corresponding elements in your list, defeating your efforts to guard the invariants of objects in the list.
If you are accepting elements to this list from client code that you don't trust or don't know about, a good practice would be to make a defense copy of x and then add that to your list. Similarly, if you will be returning an object from your list to other client code, making a defensive copy and returning that will help assure that your list remains thread safe.
Moreover, the list should be fully encapsulated in the class. By having it be public, client code anywhere can freely access the elements and make it impossible for you to protect the state of objects in the list.
I am not sure I understand Synchronized Lists in Java. Suppose I have the following:
List<Integer> numbers = Collections.synchronizedList(new ArrayList<Integer>());
// Assumption: This is running on a separate thread
public void add() {
numbers.add(new Random().nextInt(100));
}
// This is also running on a separate thread
public void doSomething() {
synchronized(numbers) {
for (int i : numbers) {}
}
}
Basically, will the add() be able to add numbers to the list if doSomething() is invoked? What would happen if I instead used public synchronized void add() and public synchronized void doSomething()?
I am working on a UDP Socket Server, and I was going to store clients in an ArrayList. I would have multiple threads that can read, write, and modify this list. What should I be doing?
will the add() be able to add numbers to the list if doSomething() is invoked?
No, not until the thread invoking doSomething() leaves the synchronized block.
What would happen if I instead used public synchronized void add() and public synchronized void doSomething()?
Assuming these are the only places where the list is used, the effect would be the same. But you would syncronize on the object containing the list rather than synchronizing on the list itself.
Basically, all the accesses to a shared state must be synchronized on the same lock. You choose the lock that you prefer. Instead of using a sychronized list, or synchronized methods, you could use a concurrent collection like a CopyOnWriteArrayList.
This should work fine. According to the docs for Collections.synchronizedList, the list mutator methods (add(), etc.) synchronize on the list object itself. Since your iteration loop is also inside a synchronized block, all should be well.
I'm trying to improve my understanding of the scope of the lock issued during a synchronized call.
Eg:
class CopyOnReadList<T> {
private final List<T> items = new ArrayList<T>();
public void add(T item) {
items.add(item);
}
public List<T> makeSnapshot() {
List<T> copy = new ArrayList<T>();
synchronized (items) {
// Make a copy while holding the lock.
for (T t : items) copy.add(t);
}
return copy;
}
}
(Code lovingly borrowed from this excellent answer)
In this code snippet, can one thread call add while another is calling makeSnapshot?. Ie., does the lock created by synchronized (items) affect all attempted reads to items, or only those attempted through the makeSnapshot() method?
The original post actually used a synchonized lock in the add method:
public void add(T item) {
synchronized (items) {
// Add item while holding the lock.
items.add(item);
}
}
What is the side effect of removing this?
It affects only those attempted in makeSnapshot() or, more generally, any other method that has synchronized(items) block (it means that it will try to aquire lock on items object and block until it's possible).
The side effect of removing synchronized block from add() method is that add() will not try to synchronize on items object, and therefore will allow concurrent modifications, including while makeSnapshot() is executing.
Without synchronize in add() you can have other threads add elements to items collection WHILE the snapshot is being made.
In this code snippet, can one thread call add while another is calling
makeSnapshot?
Certainly - and either one of the methods can then fail with a ConcurrentModificationException, or the content of the list may be corrupted.
does the lock created by synchronized (items) affect all attempted
reads to items, or only those attempted through the makeSnapshot()
method?
Neither. The lock has not effect whatsoever on the behaviour of the object items, only on blocks or methods that snychronize on it - namely to ensure that no two threads can execute any of those blocks or methods at the same time.
can one thread call add while another is calling makeSnapshot?
Yes. synchronized makes sure that any other thread can't enter another block of code which is also synchronized, on the same object (the CopyOnReadList, in this case). Since you have not synchronized the add method, several threads can call add concurrently, even if one thread is executing makeSnapshot.
By removing the synchronized on the add method, you've made the code non-threadsafe, since ArrayList is not thread-safe.
The rule of thumb is: every access (read or write) to a shared mutable state must be synchronized on the same lock.