Does the actual lock matter when deciding to use volatile? - java

Say I have the following code:
private Integer number;
private final Object numberLock = new Object();
public int get(){
synchronized(number or numberLock){
return Integer.valueOf(number);
}
}
My question is, do the following versions of the add method need to have number as volatile in the below cases:
public void add(int num){
synchronized(number)
number = number + num;
}
public void add(int num){
synchronized(numberLock)
number = number + num;
}
I understand that these are both atomic operations, but my question is, is the value of number guarennteed to be pushed out to global memory and visible to all threads without using volatile?

is the value of number guarennteed to be pushed out to global memory and visible to all threads without using volatile?
Yes. synchronization offers visibility also. Actually synchronization offers visibility and atomicity, while volatile only visibility.

You haven't synchronized get so your code is not thread-safe:
public int get(){
return Integer.valueOf(number);
}
Apart from that, synchronization will guarantee visibility as Eugene already noted.

Related

Java - Compare and Swap and synchronized Block

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.

What is the difference between synchronized fields and ReadWriteLocks?

Just want to know how the below codes that does the same functionality differs
Code 1:
class ReadWriteCounter {
ReadWriteLock lock = new ReentrantReadWriteLock();
private Integer count = 0;
public Integer incrementAndGetCount() {
lock.writeLock().lock();
try {
count = count + 1;
return count;
} finally {
lock.writeLock().unlock();
}
}
public Integer getCount() {
lock.readLock().lock();
try {
return count;
} finally {
lock.readLock().unlock();
}
}
}
Code 2:
class ReadWriteCounter {
private Integer count = 0;
public getCount()
{
synchronized(count){
return count;
}
}
public void setCount(Integer i)
{
synchronized(count){
count = i;
}
}
}
The purpose is to ensure that when count is modified no other threads access it for reading and while reading no other threads should should access it for writing. Which is an optimum solution and why? Also, I will be using this in a class where there are field variables which needs to edited. Please offer your suggestions.
ReentrantReadWriteLock is the best way to implement your thoughts.
synchronized would only allow one thread if two or more threads attempt to read count.
But everyone could get the value of count when they all attempt to read it.
Both your solutions work however there is a bug in the way you are implementing locking.
First the difference in the two approaches:
The ReentrantReadWriteLock is mainly used in situations wherein you have many more reads than writes typically in ratios of 10 reads : 1 write. This allows the reads to happen concurrently without blocking each other however when a write starts all reads will be blocked. So performance is the primary reason.
Bug in your approach :
The object on which you are locking should be final. In setCount() you are effectively swapping the object out and that can cause a dirty read at that time.
Also, never expose the object that you are locking on. The object you are locking should be private and final. The reason is if you happen to expose the object the caller may happen to use the returned object itself for locking, in which case you will run into contention issues with components outside this class itself.

Volatile arrays and memory barriers and visibility in Java

I am having difficulties understanding memory barriers and cache coherence in Java, and how these concepts relate to arrays.
I have the following scenario, where one thread modifies an array (both the reference to it and one of its internal values) and another thread reads from it.
int[] integers;
volatile boolean memoryBarrier;
public void resizeAndAddLast(int value) {
integers = Arrays.copyOf(integers, integers.size + 1);
integers[integers.size - 1] = value;
memoryBarrier = true;
}
public int read(int index) {
boolean memoryBarrier = this.memoryBarrier;
return integers[index];
}
My question is, does this do what I think it does, i.e. does "publishing" to memoryBarrier and subsequently reading the variable force a cache-coherence action and make sure that the reader thread will indeed get both the latest array reference and the correct underlying value at the specified index?
My understanding is that the array reference does not have to be declared volatile, it should be enough to force a cache-coherence action using any volatile field. Is this reasoning correct?
EDIT: there is precisely one writer thread and many reader threads.
Nope, your code is thread-unsafe. A variation which would make it safe is as follows:
void raiseFlag() {
if (memoryBarrier == true)
throw new IllegalStateException("Flag already raised");
memoryBarrier = true;
}
public int read(int index) {
if (memoryBarrier == false)
throw IllegalStateException("Flag not raised yet");
return integers[index];
}
You only get to raise the flag once and you don't get to publish more than one integers array. This would be quite useless for your use case, though.
Now, as to the why... You do not guarantee that between the first and second line of read() there wasn't an intervening write to integers which was observed by the second line. The lack of a memory barrier does not prevent another thread from observing an action. It makes the result unspecified.
There is a simple idiom that would make your code thread-safe (specialized for the assumption that a single thread calls resizeAndAddLast, otherwise more code is necessary and an AtomicReference):
volatile int[] integers;
public void resizeAndAddLast(int value) {
int[] copy = Arrays.copyOf(integers, integers.length + 1);
copy[copy.length - 1] = value;
integers = copy;
}
public int read(int index) {
return integers[index];
}
In this code you never touch an array once it got published, therefore whatever you dereference from read will be observed as intended, with the index updated.
There are multiple reasons why it wont work in general:
Java doesnt say anything about memory barriers or about the ordering
of unrelated variables. Global Memory barriers is a side effect of
x86
Even with global memory barriers: The write-order of array-reference and indexed array-value is undefined. It is guarantied that both happen-before the memory barrier, but in which order? An unsynchronized read may see the reference but not the array-value. Your read-barrier doesnt help here in case of multiple read/writes.
Beware of arrays of references: Visibility of referenced values requires special attention
A slightly better approach would be to declare the array itself as volatile and treat its values as immutable:
volatile int[] integers; // volatile (or maybe better AtomicReference)
public void resizeAndAddLast(int value) {
// enforce exactly one volatile read!
int[] copy = integers;
copy = Arrays.copyOf(copy, copy.size + 1);
copy[copy.size - 1] = value;
// may lose concurrent updates. Add synchronization or a compareExchange-loop!
integers = copy;
}
public int read(int index) {
return integers[index];
}
Unless you declare a variable volatile there is no guarantee that the thread will get the correct value. Volatile guarantees change in the variable is visible meaning instead of using the CPU cache it will write/read from main memory.
You will also need synchronization so that the reading thread does not read before the write is complete. Any reason for going with array rather than an ArrayList object because you are already using Arrays.copyOf and resizing?

Atomic operation on read/write variable in java

I have a java class as below:
public class Example implements Runnable {
private int num;
...
// Getter
public int getNum(){
return this.num;
}
// Setter
public void addToNum(int amount) {
if (this.amount> 0) {
this.num += amount;
}
}
...
}
This class can be instantiated by multiple threads. Each of this instances have its own 'num', that is, I do not want 'num' variable to be shared between all them.
To each instance, multiple threads can be accessed in concurreny in order to read/write 'num' variable. So what is the best option to protect read/write operations on 'num' variable in order to they are atomic operations?
I know that in case on C# it can be done using lock(object) like below link but in java I have no idea (I am new on it):
Atomic operations on C#
You can synchronized the methods, but you might find using AtomicInteger a faster option.
private final AtomicInteger num = new AtomicInteger();
...
// Getter
public int getNum(){
return this.num.get();
}
// Setter
public void addToNum(int amount) {
if (amount > 0) {
this.num.getAndAdd(amount);
}
}
Both of these methods are lock-less and avoid exposing a lock which could be used in an unintended way.
In Java 8, the getAndAdd uses a single machine code instruction for the addition via the Unsafe class. From AtomicInteger
private volatile int value;
public final int get() {
return value;
}
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
public synchronized void addToNum(int amount) {
if (this.num > 0) {
this.num += amount;
}
}
here you'll find documentation for it
http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/
You can use synchronized , read about it. You can synchronized methods.
In Java ,I doubt about using volatile variables because volatile variables can used only when one thread is writing and other reads are reading. Volatile works only when one thread is writing .
"where one thread (T1) modifies the counter, and another thread (T2) reads the counter (but never modifies it), declaring the counter variable volatile is enough to guarantee visibility for T2 of writes to the counter variable.
If, however, both T1 and T2 were incrementing the counter variable, then declaring the counter variable volatile would not have been enough. More on that later."
Link : http://tutorials.jenkov.com/java-concurrency/volatile.html#:~:text=The%20Java%20volatile%20keyword%20is%20intended%20to%20address%20variable%20visibility,read%20directly%20from%20main%20memory.

Simple add method Thread safe?

Having this simple class, with addition method :
class A {
public Integer add (int a, int b){
return a+b;
}
}
is it thread safe or not..? it looks safe for me, but most poeple answer no, could anyone explain why?
Thread safety should be bothered about only when you have some means of sharing state and you modify that without any locks or synchronization i.e. you modify a shared variable(class level variable) then only you should care about thread safety.
Here there is no issue of thread safety.
And in this particular case each variable is local and that location will not be shared by threads as each function call will have their on separate allocation on stack along with their local variables you should not bother anyways :)
It is completely thread safe, because all variables are local.
Actually that method is not thread safe, but it requires you to know a bit about the internals of the Integer class to understand why. Let's look at some code that yields the same bytecode:
class A {
public Integer add (int a, int b){
// auto boxing hidden in OP's implementation
return Integer.valueOf(a+b);
}
}
For small enough values the Integers are cached and looked up in a array. Using reflection you can access that array and change it's elements. Those changes are not synchronized, therefore if you change those elements, from another thread the result of your method can change too.
The following code should demonstrate the problem on most java VMs: There is a race condition in your method. In most cases it will print 4s and 5s:
import java.lang.reflect.Field;
class A {
public Integer add(int a, int b) {
return a + b;
}
private static volatile boolean cont = true;
public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InterruptedException {
final A a = new A();
new Thread(() -> {
while(cont) {
for (int i = 0; i < 100; i++) {
// print result of add method
System.out.println(a.add(2,2));
}
}
}).start();
// give other thread time to start
Thread.sleep(1);
// mess around with the internals of Integer
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
array[132] = array[133];
cont = false;
}
}
However in most cases nobody messes around with the internals of Integer. If the array in the Integer class is never modified, the values wrapped by the Integer objects returned by your method will always be correct, since the shared state used by Integer.valueOf is never modified. Therefore it would be thread-safe in that case.

Categories

Resources