How java AtomicReference works under the hood? I tried looking over the code but is based on sun.misc.Unsafe so probably another question is how Unsafe works?
This is specific to the current implementation and can change but isn't necessarily documents
How java AtomicReference works under the hood
There are two operations. Single read/writes or atomic swaps.
Single read/writes are simple volatile loads or stores.
The atomic swaps need processor level instructions. The most common implementations are Compare and Swap (CAS) found on sparc-TSO, x86, and ia64 and LL/SC found on arm, ppc and alpha. I am sure there are more that I am missing out but this gives you an idea of the scope.
another question is how Unsafe works?
Unsafe works via native methods leveraging processor instructions.
Sources:
http://gee.cs.oswego.edu/dl/jmm/cookbook.html
Some important elementary facts are as follows. 1> Different threads can only contend for instance and static member variables in the heap space. 2> Volatile read or write are completely atomic and serialized/happens before and only done from memory. By saying this I mean that any read will follow the previous write in memory. And any write will follow the previous read from memory. So any thread working with a volatile will always see the most up-to-date value. AtomicReference uses this property of volatile.
Following are some of the source code of AtomicReference. AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between. As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread[] ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the full running code.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Solution {
static List<AtomicReference<Integer>> seats;// Movie seats numbered as per
// list index
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
seats = new ArrayList<>();
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread[] ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
for (Thread t : ths) {
t.join();
}
for (AtomicReference<Integer> seat : seats) {
System.out.print(" " + seat.get());
}
}
/**
* id is the id of the user
*
* #author sankbane
*
*/
static class MyTh extends Thread {// each thread is a user
static AtomicInteger full = new AtomicInteger(0);
List<AtomicReference<Integer>> l;//seats
int id;//id of the users
int seats;
public MyTh(List<AtomicReference<Integer>> list, int userId) {
l = list;
this.id = userId;
seats = list.size();
}
#Override
public void run() {
boolean reserved = false;
try {
while (!reserved && full.get() < seats) {
Thread.sleep(50);
int r = ThreadLocalRandom.current().nextInt(0, seats);// excludes
// seats
//
AtomicReference<Integer> el = l.get(r);
reserved = el.compareAndSet(null, id);// null means no user
// has reserved this
// seat
if (reserved)
full.getAndIncrement();
}
if (!reserved && full.get() == seats)
System.out.println("user " + id + " did not get a seat");
} catch (InterruptedException ie) {
// log it
}
}
}
}
AtomicReference has two fields:-
* value, which is the reference
* valueOffset, which is the position of value in bytes from 'this', i.e. the AtomicReference
In compareAndSwap(expected, updated), the object at this-location + valueOffset is compared using == semantics with "expected", and if ==, then updated with "updated".
This is a single hardware instruction, and thus guaranteed to update or fail with false return atomically.
Read Unsafe source code from openJDK.
Related
I've been working on implementing a custom Cyclic Barrier which adds values passed into the await method and returns the sum to all threads when after notify is called.
The code:
public class Barrier {
private final int parties;
private int partiesArrived = 0;
private volatile int sum = 0;
private volatile int oldSum = 0;
public Barrier(int parties) {
if (parties < 1) throw new IllegalArgumentException("Number of parties has to be 1 or higher.");
this.parties = parties;
}
public int getParties() { return parties; }
public synchronized int waitBarrier(int value) throws InterruptedException {
partiesArrived += 1;
sum += value;
if (partiesArrived != parties) {
wait();
}
else {
oldSum = sum;
sum = 0;
partiesArrived = 0;
notifyAll();
}
return oldSum;
}
public int getNumberWaiting() { return partiesArrived; }
}
This works, but I hear that there is a way to change the values sum and oldSum (or at least oldSum) into local variables of the waitBarrier method. However, after racking my head over it, I don't see a way.
Is it possible and , if yes, how?
However, after racking my head over it, I don't see a way.
Quite so.
Is it possible and , if yes, how?
it is not possible.
For some proof:
Try marking a local var as volatile. It won't work: The compiler doesn't allow it. Why doesn't it? Because volatile is neccessarily a no-op: local vars simply cannot be shared with another thread.
One might think this is 'sharing' a local:
void test() {
int aLocalVar = 10;
Thread t = new Thread(() -> {
System.out.println("Wow, we're sharing it! " + aLocalVar);
});
t.start();
}
But it's some syntax sugar tripping you up there: Actually (and you can confirm this with javap -c -v to show the bytecode that javac makes for this code), a copy of the local var is handed to the block here. This then explains why, in java, the above fails to compile unless the variable you're trying to share is either [A] marked final or [B] could have been so marked without error (this is called 'the variable is effectively final'). Had java allowed you to access non-(effectively) finals like this, and had java used the copy mechanism that is available, that would be incredibly confusing.
Of course, in java, all non-primitives are references. Pointers, in the parlance of some other languages. Thus, you can 'share' (not really, it'll be a copy) a local var and nevertheless get what you want (share state between 2 threads), because whilst you get a copy of the variable, the variable is just a pointer. It's like this: If I have a piece of paper and it is mine, but I can toss it in a photocopier and give you a copy too, we can't, seemingly, share state. Whatever I scratch on my paper won't magically appear on yours; it's not voodoo paper. But, if there is an address to a house on my paper and I copy it and hand you a copy, it feels like we're sharing that: If you walk over to the house and, I dunno, toss a brick through a window, and I walk over later, I can see it.
Many objects in java are immutable (impervious to bricks), and the primitives aren't references. One solution is to use the AtomicX family which are just simplistic wrappers around a primitive or reference, making them mutable:
AtomicInteger v = new AtomicInteger();
Thread t = new Thread(() -> {v.set(10);});
t.start();
t.yield();
System.out.println(t.get());
// prints 10
But no actual sharing of a local happened here. The thread got a -copy- of the reference to a single AtomicInteger instance that lives on the heap, and both threads ended up 'walking over to the house', here.
You can return sum and have the first party clear it:
public synchronized int waitBarrier(int value) throws InterruptedException {
if (partiesArrived == 0) {
sum = 0;
}
partiesArrived++;
sum += value;
if (partiesArrived == parties) {
notifyAll();
} else {
while (partiesArrived < parties) {
wait();
}
}
return sum;
}
Note that the wait condition should always be checked in a loop in case of spurious wakeups. Also, sum doesn't need to be volatile if it's not accessed outside the synchronized block.
I have two threads to sell tickets.
public class MyThread {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread1 = new Thread(()->{
for (int i = 0; i < 30; i++) {
ticket.sell();
} }, "A");
thread1.start();
Thread thread2 = new Thread(()->{
for (int i = 0; i < 30; i++) {
ticket.sell();
} }, "B");
thread2.start();
}
}
class Ticket {
private Integer num = 20 ;
private Object obj = new Object();
public void sell() {
// why shouldn't I use "num" as a monitor object ?
// I thought "num" is unique among two threads.
synchronized ( num ) {
if (this.num >= 0) {
System.out.println(Thread.currentThread().getName() + " sells " + this.num + "th ticket");
this.num--;
}
}
}
}
The output will be wrong if I use num as a monitor object.
But if I use obj as a monitor object, the output will be correct.
What's the difference between using num and using obj ?
===============================================
And why does it still not work if I use (Object)num as a monitor object ?
class Ticket {
private int num = 20 ;
private Object obj = new Object();
public void sell() {
// Can I use (Object)num as a monitor object ?
synchronized ( (Object)num ) {
if (this.num >= 0) {
System.out.println(Thread.currentThread().getName() + " sells " + this.num + "th ticket");
this.num--;
}
}
}
}
Integer is a boxed value. It contains a primitive int, and the compiler deals with autoboxing/autounboxing that int. Because of this, the statement this.num-- is actually:
num=Integer.valueOf(num.intValue()-1)
That is, the num instance containing the lock is lost once you perform that update.
The fundamental problem here is synchronizing on a non-final value.
The most important thing to understand about the Java Memory Model - that is, what values a thread sees whilst executing a Java program - is the happens-before relationship.
In the specific case of a synchronized block, actions done in one thread before exiting the synchronized block happen before actions done inside the synchronized block in another thread - so, if the first thread increments a variable inside that synchronized block, the second thread sees that updated value.
This goes over and above the well-known fact that a synchronized block can only be entered by one thread at a time: only one thread at a time and you get to see what the previous thread did.
// Thread 1 // Thread 2
synchronized (monitor) {
num = 1
} // Exiting monitor
// *happens before*
// entering monitor
synchronized (monitor) {
int n = num; // Guaranteed to see n = 1 (provided no other thread has entered a block synchronized on monitor and changed it first).
}
There is a very important caveat to this guarantee: it only holds if the two executions of the synchronized block use the same monitor. And that's not the same variable, it's the same actual concrete object on the heap (variables don't have monitors, they're just pointers to a value in the heap).
So, if you reassign the monitor inside the synchronized block:
synchronized (num) {
if (num > 0) {
num--; // This is the same as `num = Integer.valueOf(num.intValue() - 1);`
}
}
then you are destroying the happens-before guarantee, because the next thread to arrive at that synchronized block is entering the monitor of a different object (*).
Once you do, the behavior of your program is ill-defined: if you're lucky, it fails in an obvious way; if you're very unlucky, it can seem to work, and then start failing mysteriously at a later date.
Your code is just broken.
This isn't something that's specific to Integers either: this code would have the same problem.
// Assume `Object someObject = new Object();` is defined as a field.
synchronized (someObject) {
someObject = new Object();
}
(*) Actually, you still get a happens-before relationship for the new object: it's just not for the things inside this synchronized block, it's for things that happened in some other synchronized block that used the object as the monitor. Essentially, it's impossible to reason about what this means, so you may as well just consider it "broken".
The correct way to do it is to synchronize on a field that you can't (not just don't) reassign. You could simply synchronize on this (which can't be reassigned):
synchronized (this) {
if (num > 0) {
num--; // This is the same as `num = Integer.valueOf(num.intValue() - 1);`
}
}
Now it doesn't matter that you're reassigning num inside the block, because you're not synchronizing on it any more. You get the happens-before guarantee from the fact that you're always synchronizing on the same thing.
Note, however, that you must always access num from inside a synchronized block - for example, if you have a getter to get the number of tickets remaining, that must also synchronize on this, in order to get the happens-before guarantee that the value changed in the sell() method is visible in that getter.
This works, but it may not be entirely desirable: anybody who has access to a reference to your Ticket instance can also synchronize on it. This means they can potentially deadlock your code.
Instead, it is a common practice to introduce a private field which is used purely for locking: this is what the obj field gives you. The only modification from your code should be to make it final (and give it a better name than obj):
private final Object obj = new Object();
This can't be accessed outside your class, so nefarious clients cannot cause a deadlock for you directly.
Again, this can't be reassigned inside your synchronized block (or anywhere else), so there is no risk of you breaking the happens-before guarantee by reassigning it.
I am referencing from Baeldung.com. Unfortunately, the article does not explain why this is not a thread safe code. Article
My goal is to understand how to create a thread safe method with the synchronized keyword.
My actual result is: The count value is 1.
package NotSoThreadSafe;
public class CounterNotSoThreadSafe {
private int count = 0;
public int getCount() { return count; }
// synchronized specifies that the method can only be accessed by 1 thread at a time.
public synchronized void increment() throws InterruptedException { int temp = count; wait(100); count = temp + 1; }
}
My expected result is: The count value should be 10 because of:
I created 10 threads in a pool.
I executed Counter.increment() 10 times.
I make sure I only test after the CountDownLatch reached 0.
Therefore, it should be 10. However, if you release the lock of synchronized using Object.wait(100), the method become not thread safe.
package NotSoThreadSafe;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CounterNotSoThreadSafeTest {
#Test
void incrementConcurrency() throws InterruptedException {
int numberOfThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
CounterNotSoThreadSafe counter = new CounterNotSoThreadSafe();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
try { counter.increment(); } catch (InterruptedException e) { e.printStackTrace(); }
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This code has both of the classical concurrency problems: a race condition (a semantic problem) and a data race (a memory model related problem).
Object.wait() releases the object's monitor and another thread can enter into the synchronized block/method while the current one is waiting. Obviously, author's intention was to make the method atomic, but Object.wait() breaks the atomicity. As result, if we call .increment() from, let's say, 10 threads simultaneously and each thread calls the method 100_000 times, we get count < 10 * 100_000 almost always, and this isn't what we'd like to. This is a race condition, a logical/semantic problem. We can rephrase the code... Since we release the monitor (this equals to the exit from the synchronized block), the code works as follows (like two separated synchronized parts):
public void increment() {
int temp = incrementPart1();
incrementPart2(temp);
}
private synchronized int incrementPart1() {
int temp = count;
return temp;
}
private synchronized void incrementPart2(int temp) {
count = temp + 1;
}
and, therefore, our increment increments the counter not atomically. Now, let's assume that 1st thread calls incrementPart1, then 2nd one calls incrementPart1, then 2nd one calls incrementPart2, and finally 1st one calls incrementPart2. We did 2 calls of the increment(), but the result is 1, not 2.
Another problem is a data race. There is the Java Memory Model (JMM) described in the Java Language Specification (JLS). JMM introduces a Happens-before (HB) order between actions like volatile memory write/read, Object monitor's operations etc. https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5 HB gives us guaranties that a value written by one thread will be visible by another one. Rules how to get these guaranties are also known as Safe Publication rules. The most common/useful ones are:
Publish the value/reference via a volatile field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5), or as the consequence of this rule, via the AtomicX classes
Publish the value/reference through a properly locked field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5)
Use the static initializer to do the initializing stores
(http://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4)
Initialize the value/reference into a final field, which leads to the freeze action (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5).
So, to have the counter correctly (as JMM has defined) visible, we must make it volatile
private volatile int count = 0;
or do the read over the same object monitor's synchronization
public synchronized int getCount() { return count; }
I'd say that in practice, on Intel processors, you read the correct value without any of these additional efforts, with just simple plain read, because of TSO (Total Store Ordering) implemented. But on a more relaxed architecture, like ARM, you get the problem. Follow JMM formally to be sure your code is really thread-safe and doesn't contain any data races.
Why int temp = count; wait(100); count = temp + 1; is not thread-safe? One possible flow:
First thread reads count (0), save it in temp for later, and waits, allowing second thread to run (lock released);
second thread reads count (also 0), saved in temp, and waits, eventually allowing first thread to continue;
first thread increments value from temp and saves in count (1);
but second thread still holds the old value of count (0) in temp - eventually it will run and store temp+1 (1) into count, not incrementing its new value.
very simplified, just considering 2 threads
In short: wait() releases the lock allowing other (synchronized) method to run.
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.
I am very puzzled by the behavior of MySQL and java threading. I declare this as synchronized and the results I get are clashing. That means that more than one thread is accessing the same function at the same time. This code segment is in the runnable class.
MachineID is the thread id in the order with which it was invoked in the for loop. (It is jsut a number from 1 to 100).
I don't think the table is required information to
This is the output I get
144 18
144 17
144 11
144 13
144 10
144 9
public synchronized int getRow() throws SQLException{
String query="SELECT * FROM Searches WHERE checked='0'";
ResultSet results = this.database.executeQuery(query);
int id=0;
if(results.next()){
id=results.getInt(1);
System.out.println(id+" "+this.machineID);
query = "UPDATE Searches SET checked='1' WHERE ID_num='"+id+"'";
System.out.println(this.database.executeUpdate(query));
}
return id;
}
public void run() {
int id=getRow();
if (id!=0) {
}
}
this is where I invoke my threads
for (int i = 0; i < verifier.length; i++) {
verifier[i]=new Thread(new Verifier(main.database,i+1));
verifier[i].start();
}
Assuming the getRow() method belongs to the Verifier class, then there is no blocking going on. When you declare synchronized on a method, it is equivalent to synchronizing on the instance itself. However, you are spawning a new Verifier instance for each Thread. Each of those is synchronizing on themselves so none block any of the others.
Consider sharing a Lock object with each instance of Verifier or synchronizing on a shared object.
Object lock = new Object();
for (int i = 0; i < verifier.length; i++) {
verifier[i]=new Thread(new Verifier(main.database,i+1, lock));
verifier[i].start();
}
...
public int getRow() throws SQLException{
synchronized(lock) {
...
}
}
Sotirios has hit the nail on the head. But instead of having a new variable to lock on, I would use just a single Verifier, and call it from multiple threads. So you'll have
Verifier oneVerifier = new Verifier(main.database, 1);
for (int i = 0; i < verifier.length; i++) {
verifier[i]=new Thread(oneVerifier);
verifier[i].start();
}
Note - I don't know what that second argument to the Verifier constructor is supposed to be. Chances are, you don't actually need it, but since you don't actually show the constructor, I thought I'd leave it in.
No synchronization is happening at all it's is similar to
synchronize(this)
And the same instance is not shared across the threads so there is no synchronization happening at all.
So you need to share a lock object across the Runnable instances i.e. Verifier in constructer like:
public class Verifier implements Runnable{
private final Object lock;
public Verifier(Object lock){
this.lock=lock;
}
Than you can synchronize on the lock like:
synchronize(lock)
else you can synchronize on the class object as well:
synchronize(Verifier.class)