I understand (or at least I think I do;) ) the principle behind volatile keyword.
When looking into ConcurrentHashMap source, you can see that all nodes and values are declared volatile, which makes sense because the value can be written/read from more than one thread:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val;
volatile Node<K,V> next;
...
}
However, looking into ArrayBlockingQueue source, it's a plain array that is being updated/read from multiple threads:
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
How is it guaranteed that the value inserted into items[putIndex] will be visible from another thread, providing that the element inside the array is not volatile (i know that declaring the array itself doesnt have any effect anyhow on the elements themselves) ?
Couldn't another thread hold a cached copy of the array?
Thanks
Notice that enqueue is private. Look for all calls to it (offer(E), offer(E, long, TimeUnit), put(E)). Notice that every one of those looks like:
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
// Do stuff.
enqueue(e);
} finally {
lock.unlock();
}
}
So you can conclude that every call to enqueue is protected by a lock.lock() ... lock.unlock() so you don't need volatile because lock.lock/unlock are also a memory barrier.
According to my understanding volatile is not needed as all BlockingQueue implementations already have a locking mechanism unlike the ConcurrentHashMap.
If you look at he public methods of the Queue you will find a ReentrantLock that guards for concurrent access.
Related
public class SimulatedCAS {
private int value;
public synchronized int get() { return value; }
public synchronized int compareAndSwap(int expectedValue, int newValue)
{
int oldValue = value;
if (oldValue == expectedValue)
value = newValue;
return oldValue;
}
}
public class CasCounter
{
private SimulatedCAS value;
public int getValue()
{
return value.get();
}
public int increment()
{
int value.get();
while (v != value.compareAndSwap(v, v + 1))
{
v = value.get();
}
}
}
I refereed a Book "Java Concurrency in Practice"
a Counter must be increased by multiple threads. I tried using the compare and swap method but at the end it make used of synchronized keyword which might again result in blocking and waiting of threads. using a synchronized block provides me the same performance can anybody state. what is the difference between using compare and swap and synchronized block ? or any other way to implement compare and swap without using synchronized block.
I need to increment counter with multiple threads
The AtomicInteger class is good for that.
You can create it with final AtomicInteger i=new AtomicInteger(initial_value); Then you can call i.set(new_value) to set its value, and you can call i.get() to get its value, and most importantly for your application, you can call i.incrementAndGet() to atomically increment the value.
If N different threads all call i.incrementAndGet() at "the same time," then
Each thread is guaranteed to see a different return value, and
The final value after they're all done is guaranteed to increase by exactly N.
The AtomicInteger class has quite a few other methods as well. Most of them make useful guarantees about what happens when multiple threads access the varaible.
Real Compare and Swap does optimistic locking. It changes value and then makes a rollback if something has changed the variable simultaneously. So, if the variable is modified rarely, then CAS performs better, than synchronized.
But if the variable is modified often, then synchronized performs better, because it doesn't allow anything to mess with the variable while it is changed. And so there's no need to make an expensive rollback.
The code is from ArrayBlockingQueue,JAVA 8.
The comment says:Lock only for visibility, not mutual exclusion.
final Object[] items;
int putIndex;
int count;
public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c) {
this(capacity, fair);
final ReentrantLock lock = this.lock;
lock.lock(); // Lock only for visibility, not mutual exclusion
try {
int i = 0;
try {
for (E e : c) {
checkNotNull(e);
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalArgumentException();
}
count = i;
putIndex = (i == capacity) ? 0 : i;
} finally {
lock.unlock();
}
}
I think the lock guarantees the visibility of count&putIndex.
But why dont use volatile?
The lock guarantees the visibility of all writes during: to count, to putIndex, and to the elements of items that it changes.
It doesn't need to guarantee mutual exclusion, as it is in the constructor and since the reference to this hasn't been given to other threads, there is no need for mutual exclusion (but it would guarantee that as well if the reference to this was given out before that point)
The comment is merely saying that the purpose of the lock is the visibility effects.
As to why you can't use volatile:
The methods that retrieve values from the queue, like poll, take and peek do need to lock for mutual exclusion. Making a variable volatile is not necessary; it could have an adverse performance impact.
It would also be hard to get it right because of the ordering: a volatile write happens before (JLS terminology) a volatile read on the same variable. That means that the constructor would have to write to the volatile variable as its last action, while all code that needs to be correctly synchronized needs to read that volatile variable first before doing anything else.
Locks are much easier to reason about and to get the ordering of accesses right, and, in this case - they are required in any case to execute multiple writes as one atomic action.
The lock guarantees all writes will be visible, including writes to the items array. Making the array volatile would not be enough to ensure writes to array elements are visible to all threads.
There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work.
above is in https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.3
But I found LOCK used in ArrayBlockingQueue's Constructor. Why it is used ?
public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
this(capacity, fair);
final ReentrantLock lock = this.lock;
lock.lock(); // Lock only for visibility, not mutual exclusion
try {
int i = 0;
try {
for (E e : c) {
checkNotNull(e);
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalArgumentException();
}
count = i;
putIndex = (i == capacity) ? 0 : i;
} finally {
lock.unlock();
}
}
The comment // Lock only for visibility, not mutual exclusion tells you about it. Depending on the CPU we can have a situation where the constructing thread "leaves" our constructor but the fields are not yet initialized (so in our example thread leaves ArrayBlockingQueue constructor but our count, putIndex, items fields are not yet initialized and some other thread started using offer/add methods). The same lock strategy is used in LinkedBlockingQueue. Also, JVM have capabilities to reorder our bytecode instructions inside our method/constructor. And for last there may be a situation that a thread can obtain a reference before another thread finishes constructing the object.
Here you can read more about it:
Constructor synchronization in Java
And also, there are many blog posts about Memory Visibility.
I have seen the following code, and I think that there is a useless while loop in the implementation of addElement method. It should never happen to have more elements than size+1 since there is already a write lock.
So why is the addElement method removing elements till it gets this condition
true
while(concurrentLinkedQueue.size() >=maxSize)
Any pointers around this would be great.
Here is the Implementation:
public class LRUCache<K,V> {
private ConcurrentLinkedQueue<K> concurrentLinkedQueue = new ConcurrentLinkedQueue<K>();
private ConcurrentHashMap<K,V> concurrentHashMap = new ConcurrentHashMap<K, V>();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private Lock readLock = readWriteLock.readLock();
private Lock writeLock = readWriteLock.writeLock();
int maxSize=0;
public LRUCache(final int MAX_SIZE){
this.maxSize=MAX_SIZE;
}
public V getElement(K key){
readLock.lock();
try {
V v=null;
if(concurrentHashMap.contains(key)){
concurrentLinkedQueue.remove(key);
v= concurrentHashMap.get(key);
concurrentLinkedQueue.add(key);
}
return v;
}finally{
readLock.unlock();
}
}
public V removeElement(K key){
writeLock.lock();
try {
V v=null;
if(concurrentHashMap.contains(key)){
v=concurrentHashMap.remove(key);
concurrentLinkedQueue.remove(key);
}
return v;
} finally {
writeLock.unlock();
}
}
public V addElement(K key,V value){
writeLock.lock();
try {
if(concurrentHashMap.contains(key)){
concurrentLinkedQueue.remove(key);
}
while(concurrentLinkedQueue.size() >=maxSize){
K queueKey=concurrentLinkedQueue.poll();
concurrentHashMap.remove(queueKey);
}
concurrentLinkedQueue.add(key);
concurrentHashMap.put(key, value);
return value;
} finally{
writeLock.unlock();
}
}
}
the point here is, i guess, that you need to check if the LRU is at it's maximum size. the check here is NOT (map.size() > maxSize), it is ">=". now, you could probably replace that with "if (map.size() == maxSize) {...}" - which, in ideal conditions, should do exactly the same thing.
but in not-so-ideal conditions, if for whatever reason, somebody put an EXTRA entry in the map without checking, then with this code, the map would NEVER go down in size again, because the if condition would never be true.
so - why not "while" and ">=" instead of "if" and "=="? same amount of code, plus more robust against "unexpected" conditions.
An easy implementation of an LRU cache does the following, a while loop is only need when the max size is adjusted, but not for the primitive operations:
During put, remove superflous element.
During get, move element to top.
The primitive operations will be one shot. You can then use either ordinary synchronized or read write lock around this data structure.
When using read write locks the fairness on who comes first is then rather an issue of the used read write locks than of the LRU cache itself.
Here is a sample implementation.
It's not wrong but just a safety in case of accidental modification. You could check for equality with concurrentLinkedQueue.size() == maxSize in a conditional statement.
I'm Learning Java multithreading and I have problem, I can't understand Semaphores. How can I execute threads in this order? for example : on image1 : the 5-th thread start running only then 1-st and 2-nd is finished to execute.
Image 2:
Image 1:
I upload now images for better understanding . :))
Usually in java you use mutexes (also called monitors), which prohibits that two or more threads access the code region proctected by that mutex
That code region is defined using the sychronized statement
sychronized(mutex) {
// mutual exclusive code begin
// ...
// ...
// mutual exclusive code end
}
where mutex is defined as e.g:
Object mutex = new Object();
To prevent a task from beeing started you need advanced technics, such as barriers, defined in java.util.concurrency package.
But first make yourself confortable with the synchronized statement.
If you think that you will often use multi threading in java, you might want to read
"Java Concurrency in Practise"
Synchronized is used so that each thread will enter that method or that portion of the code on at a time. If you want to
public class CountingSemaphore {
private int value = 0;
private int waitCount = 0;
private int notifyCount = 0;
public CountingSemaphore(int initial) {
if (initial > 0) {
value = initial;
}
}
public synchronized void waitForNotify() {
if (value <= waitCount) {
waitCount++;
try {
do {
wait();
} while (notifyCount == 0);
} catch (InterruptedException e) {
notify();
} finally {
waitCount--;
}
notifyCount--;
}
value--;
}
public synchronized void notifyToWakeup() {
value++;
if (waitCount > notifyCount) {
notifyCount++;
notify();
}
}
}
This is an implementation of a counting semaphore. It maintains counter variables ‘value’, ‘waitCount’ and ‘notifyCount’. This makes the thread to wait if value is lesser than waitCount and notifyCount is empty.
You can use Java Counting Semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. For example, here is a class that uses a semaphore to control access to a pool of items:
class Pool {
private static final MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an item is available for use. When the thread has finished with the item it is returned back to the pool and a permit is returned to the semaphore, allowing another thread to acquire that item. Note that no synchronization lock is held when acquire() is called as that would prevent an item from being returned to the pool. The semaphore encapsulates the synchronization needed to restrict access to the pool, separately from any synchronization needed to maintain the consistency of the pool itself.
A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations), that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.