A LinkedList
has convenient peek
, pop
, ... methods.
Unfortunately, I need a thread-safe LinkedList
. So, my first idea was to wrap it as follows:
List<Object> list = Collections.synchronizedList(new LinkedList<>());
However, since the List
interface does not contain the peek
or pop
methods. This doesn't work of course.
Alternatively, I could use synchronized(list)
blocks all over the code. Is that the way to go ?
Any solutions that I'm overlooking ?
EDIT:
There are many reasons why one would use a LinkedList
. I see some people are proposing other collections. So, here follow the brief requirements, which lead to my decision of using a LinkedList
.
More background information:
peek
ed and validated. If validation fails, then the item needs to stay in the list.If you need peek
to work, making a synchronized wrapper may not be sufficient, so you would have to write synchronized
explicitly.
It is not so much a problem with writing a wrapper as it is a problem with the semantic of the peek
method. Unlike the pop
method, which represents a single action, peek
method is often used in a multi-component action composed of peek
-ing and then doing something else based on what peek
returns.
If you synchronize in a wrapper, the result would be the same as if you wrote this code manually:
String s;
synchronized(list) {
s = list.peek();
}
// <<== Problem ==>>
if (s != null) {
synchronized(list) {
s = list.pop();
}
}
This presents a problem, because there is a moment in time when your list can change in between of peek
and pop
(this place in code above is marked as "Problem").
A proper way to do check-and-modify is doing it in a single synchronized
block, i.e.
synchronized(list) {
String s = list.peek();
if (s != null) {
s = list.pop();
}
}
However, this cannot be done in a simple wrapper, because two list operations are performed in a single synchronized
block.
You can avoid writing synchronized
in multiple places by building your own data structure that encapsulates a LinkedList<T>
, and provides operations that perform all test-and-modify operations in a synchronized block. This is not a simple problem, however, so you may be better off changing your algorithm in a way that it could work with one of pre-defined concurrent containers.
What you want is a concurrent Queue
. LinkedList
implements List
, Deque
, and Queue
. The Queue
is what gives it the FIFO (adding in back, remove from front) semantics with peek and pop.
A LinkedBlockingQueue can be bounded, which is one of your criteria. There are several other concurrent Queues and Deques to choose from as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With