Reputation: 9829
Is the following code thread-safe on concurrent access to List?
Does the volatile qualifies add any value here?
class concurrentList{
private AtomicBoolean locked = new AtomicBoolean(true);
volatile List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public void push(int e){
while(!locked.get());
list.add(e);
while(!locked.compareAndSet(true,false));
}
public int pop(){
int elem;
while(locked.get());
elem=(Integer)list.remove(0);
while(!locked.compareAndSet(false,true));
return elem;
}
....
}
Upvotes: 3
Views: 728
Reputation: 2641
Adding more to already added in answer i.e For any concurrent programming three concepts, you need to consider while writing a thread safe programming .When a concurrent program is not correctly written, the errors tend to fall into one of the three categories: Aomicity, Visibility, or Ordering.
Atomicity :deals with which actions and sets of actions have indivisible effects.It is usually thought of in terms of mutual exclusion.
Visibility :Determines when the effects of one thread can be seen by another.
Ordering :Determines when actions in one thread can be seen to occur out of order with respect to another
In your code First issue it is failing all mentioned above concepts.You are not using lock so the visibility and ordering will not be ensure.
For thread safe you can use ReadWriteLock
in concurrent API.Or there is available non-blocking linked-list which will use compareAndset.
Upvotes: 0
Reputation: 11620
Inn such cases I would recommend use ReadWriteLock. This lock has two uses. When readLock is on, no reads are allowed, untill write lock is released.Read lock is non blocking:
class concurrentList{
ReadWriteLock lock =new ReentrantReadWriteLock();
private AtomicBoolean locked = new AtomicBoolean(true);
volatile List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public void push(int e){
lock.writeLock().lock();
try{
list.add(e);
} finally {
lock.writeLock().unlock();
}
}
public int pop(){
lock.readLock().lock();
try {
int elem;
elem=(Integer)list.remove(0);
} finally {
lock.readLock().unlock();
}
return elem;
}
.... }
Upvotes: 1
Reputation: 16214
In this particulary case, I would use synchronized for the methods, and not volatile for the variable according to [this question][1]
class concurrentList{
private AtomicBoolean locked = new AtomicBoolean(true);
List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public synchronized void push(int e){
while(someLock.notCondition()); //only an example
list.add(e);
someLock.notify();
}
public synchronized int pop(){
int elem;
while(someLock.notCondition());
elem=(Integer)list.remove(0);
someLock.notify()
return elem;
}
....
}
Upvotes: 0
Reputation: 692081
No, it's not thread-safe. Two threads calling push()
can perfectly both read the locked as true, then add concurrently to the linked list. Since a LinkedList is not thread-safe, your code is not thread-safe.
To lock, use a lock, not an AtomicBoolean.
Upvotes: 2