AtomicReference Usage - java

Say you have the following class
public class AccessStatistics {
private final int noPages, noErrors;
public AccessStatistics(int noPages, int noErrors) {
this.noPages = noPages;
this.noErrors = noErrors;
}
public int getNoPages() { return noPages; }
public int getNoErrors() { return noErrors; }
}
and you execute the following code
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
In the last two lines
newValue = new AccessStatistics(noPages, noErrors);
while (!stats.compareAndSet(prev, newValue))
Does it means the new created AccessStatistics instance has same reference as the current AccessStatistics instance. how could it be ? Can Anyone explain it . Thanks a lot.

stats.compareAndSet(prev, newValue) will fail and return false if the current reference held by stats is not prev.
Typically, in a multi-threaded environment, it is very possible that between prev = stats.get(); and stats.compareAndSet(prev, newValue); another thread would have modified the reference held by stats.
stats.compareAndSet(prev, newValue); really says:
if stats still holds a reference to prev, as it was 5 lines before, update it to hold a reference to newValue
if however another thread has already changed the reference held by stats since I last checked 5 lines ago, discard my calculation and loop to recalculate a new newValue.

The newly created object is, well, new. After the line that it is created, the only thing that refers to it is newValue. Nothing else could -- how could it? The compareAndSet() only sets if nothing else has in the meantime set it to some third value, besides the old one you know about prev and the new one you made newValue.

Related

How do I detect if a value has been added to array slot? (java)

I am a beginner programmer and i've gotten stuck.
I've set up an array here which has worked how I want it to.
Although now I need a way to check the very last slot (data[5]) to see if any value has been placed within it since there is no guarantee in my code that each array slot will be assigned a value.
Below is my working array setup:
public final int[] data;
//Constructor
public MyArrayList() {
this.data = new int[6];
}
And here is what I've tried:
if(data[5] == null){
data[5] = value;
truth = true;
} else {
truth = false;
}
Note that this code is trying to detect if anything is in there, and place another value in if it can see there hasn't been any code written there.
Any help appreciated :)
int is a primitive type in Java, so it will never be null. If you want to keep track of how much of the array you've "used", you can add a second field to the class to keep up with it.
public class MyArrayList {
private final int[] data;
private int index;
public MyArrayList() {
data = new int[6];
index = 0;
}
...
}
Then whenever you "push" something new to the list, you put it at the index position and increment index. If index is ever equal to the length of the list, then you've exhausted the space you allocated.
Use the Integer class instead of the primitive type. It allows to assign a value or a null value. With this you can apply the logic that you described.
data = new Integer[6];
if (data[5] == null)
data[5] = value;

explain Linked List data structure in Java

Iknow java is passed by value. For linked list data structure, what is the difference between method size() and size1()? I think there are the same becasue the head and next reference point to the same thing in size1(). but the result is difference
public class IntList {
int item;
IntList next;
public IntList(int item, IntList next){
this.item = item;
this.next = next;
}
public int size(){
int size = 1;
while (next !=null){
size++;
next = next.next;
}
return size;
}
public int size1(){
int size = 1;
IntList head = next;
while (head != null){
size++;
head = head.next;
}
return size;
}
public static void main(String[] args) {
IntList L = new IntList(1,null);
L = new IntList(2,L);
L = new IntList(3,L);
L = new IntList(10,L);
L = new IntList(20,L);
System.out.println(L.size());
}
}
I am confused about the reference means in java.
This is a matter of issue with scope. In size1(), you are creating a local variable named head. When you call size1() it creates a reference variable that will be destroyed at the end of the call. This means that no matter how many times you call size1(), it will always give you the proper size.
However, when you use the field "next" in size(), it iterates through each variable until the end. However, once it gets there, it is notdestroyed because its scope is the object. This means the next time you call size(), and all subsequent calls (given no changes), it will always return 1.
They're logically the same, but size() is actually pointing next to the final node, so the next size check will return 1. size1() uses a local variable to traverse the list, so the object state isn't affected.

Boolean not changing in thread

I have a class MPClient and MultiplayerMatch. MultiplayerMatch, in his constructor, creates a MPClient runnable thread.
To avoid data overflow, I have a boolean named "moved" in MultiplayerMatch that changes to true when the player is moving.
In the updateMatch method, if there's any player movement, "moved" changes to true, which allow MPClient to enter an if statment (inside while). This way MPClient only sends data to the server when something changes on the game.
Neverthless, when the flag is true, in MPClient that change is not registed! MPClient still "thinks" moved equals false, even after that flag changed in MultiplayerMatch, and as a consequence, nothing is sent to the server...
After a few tests, I noticed that if I run it in Debug Mode, since I have some breakpoints, that change is registered and everything works great!
Why is the boolean change only "seen" though Debug Mode? Does it have something to do with the app "running speed", since there are breakpoints?
Here's only the important part of the code:
MPClient:
public class MPClient {
static final int TIME_OUT = 5000;
Client client;
MultiPlayMatch match;
public MPClient(String name, int team, MultiPlayMatch match) {
this.match = match;
client = new Client();
client.start();
Network.registerPackets(client);
addListeners();
try {
client.connect(TIME_OUT, "127.0.0.1", Network.PORT);
} catch (IOException e) {
e.printStackTrace();
client.stop();
}
/*this comment is just to show that here is the place where the login information is sent to the server, instead of showing all the code*/
PlayerInfo playerInfo = new PlayerInfo();
Network.UpdatePlayer updatePlayer = new Network.UpdatePlayer();
updatePlayer.name = name;
updatePlayer.team = team;
while(true) {
if(match.moved) { //--> this is the variable that is always false
playerInfo.x = match.getClientPlayerX(team);
playerInfo.y = match.getClientPlayerY(team);
updatePlayer.x = playerInfo.x;
updatePlayer.y = playerInfo.y;
client.sendTCP(updatePlayer);
match.moved = false;
}
}
}
private void addListeners() {
client.addListener(new Listener.ThreadedListener(new Listener() {
#Override
public void received(Connection connection, Object object) {
if(object instanceof Network.UpdatePlayer) {
Network.UpdatePlayer updatePlayer = (Network.UpdatePlayer) object;
match.setPlayerPosition(updatePlayer.x, updatePlayer.y, updatePlayer.name, updatePlayer.team);
}
}
}));
}
}
MultiplayerMatch:
public class MultiPlayMatch extends Match {
public boolean moved;
public MultiPlayMatch(){
super(0);
Random r = new Random();
int aux = r.nextInt(2);
aux = 0;
if(aux == 0){
homeTeam = new Team("Benfica", Team.TeamState.Attacking, w);
visitorTeam = new Team("Porto", Team.TeamState.Defending, w);
} else{
homeTeam = new Team("Benfica", Team.TeamState.Defending, w);
visitorTeam = new Team("Porto", Team.TeamState.Attacking, w);
}
//homeTeam.controlPlayer(0);
numberOfPlayers = 0;
moved = false;
}
#Override
public void updateMatch(float x, float y, Rain rain, float dt) {
homeTeam.updateControlledPlayerOnline(x, y);
rain.update();
w.step(Constants.GAME_SIMULATION_SPEED, 6, 2);
if(x != 0 || y != 0) moved = true; //this is the place the variable is changed, but if it isn't in debug mode, MPClient thinks it's always false
}
public void setPlayerPosition(float x, float y, String name, int team) {
if(team == 0)
homeTeam.changePlayerPosition(x, y, name);
else
visitorTeam.changePlayerPosition(x, y, name);
}
}
volatile
This is because it is reading a cached value of match.moved variable instead of the latest. To avoid this, declare the variable as volatile
public volatile boolean moved;
Read more here
tl;dr
AtomicBoolean is a convenient alternative to volatile.
This class wraps and protects a nested primitive boolean value while ensuring proper visibility.
Instantiate:
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
Getter:
boolean x = moved.get() // Returns current value.
Setter:
moved.set( false ) // Sets a new value.
Get, then set:
boolean x = moved.getAndSet( false ) ; // Retrieves the old value before setting a new value.
AtomicBoolean
The Answer by agamagarwal is correct. You have fallen into the visibility conundrum that occurs when accessing variables across threads. One solution is the use of volatile shown there.
Another solution is the Atomic… classes bundled with Java. In this case, AtomicBoolean.
The Atomic… classes wrap a value, and add thread-safe methods for accessing and setting that value.
I often prefer using the Atomic… classes rather than volatile. One reason for this preference is that it makes quite clear and obvious to the user that we are using a protected resource across threads.
Instantiation:
public class MultiPlayMatch extends Match {
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
…
Notice two things about that instantiation:
final ensures that we do not swap out one AtomicBoolean object for another. Such swapping would put us right back into the variable visibility conundrum we are trying to escape.
The AtomicBoolean object is being instantiated at the same time as this outer object (MultiPlayMatch in your case) is being instantiated. So we have ensured that an instance of AtomicBoolean exists before any access, including any access across threads. If we waited until later (“lazy” loading), then we would be falling back into that variable visibility conundrum we are trying to escape.
Getting the value:
if ( this.match.moved.get() ) { … // Returns the primitive `true` or `false` value wrapped within this `AtomicBoolean` object.
And setting the value:
this.match.moved.set( false ) ;
You may want to get the current value while also setting a value in an immediate thread-safe “atomic” (combined) operation:
boolean oldValue = this.match.moved.getAndSet( false ) ;
To learn all about concurrency in Java, see the book, Java Concurrency in Practice by Brian Goetz, et al.

Why another branch is unreachable in my code?

Why the output of the following code is always suck. How to get happy as the output? Why the happy branch is unreachable?
public class HowToMakeStackoverflowBetter {
private static final int HUMAN_PATIENCE = 10;
private List<Member> members = new ArrayList<>();
private int atmosphere = -10;
private Random r = new Random();
public HowToMakeStackoverflowBetter(int size) {
for (int i = 0; i < size; i++) { members.add(new Member()); }
}
public Member pick() { return members.get(r.nextInt(members.size())); }
public class Member {
private int patience = HUMAN_PATIENCE;
private Question question = null;
public Member() { patience = r.nextInt(patience+1) + atmosphere; }
public void vote(Question q) {
if (patience >= 0) {
voteUp(q);
} else {
voteDown(q);
}
}
public void ask() {
question = new Question();
for (Member member : members) {
member.vote(question);
}
}
private void voteUp(Question q) { ++q.vote; }
private void voteDown(Question q) { --q.vote; }
public String toString() {
return (question.vote >= 0)? "Happy!" : "Suck!";
}
}
public class Question { private int vote; }
public static void main(String[] args) {
HowToMakeStackoverflowBetter stackoverflow = new HowToMakeStackoverflowBetter(100);
Member me = stackoverflow.pick();
me.ask();
System.out.println(me);
}
}
After a 1000 times loop, it gives us 1000 sucks. I remember 2 or 3 years ago, this was not the case. Something changed.
Two problems. First:
linkedList::linkedList(){
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel.str="I am sentinel!!";
};
sentinel is your member variable, and .last is its pointer to another node. This hasn't been initialised, so trying to use it is undefined behaviour. In practice, it's effectively pointing at a random address in (or out of) memory, and you attempt to dereference the pointer then copy the entire sentinel object over the node at the imagined pointed-to address: i.e. you try to copy the 3 pointers in the sentinel node member variable to a random address in memory.
You probably want to do this:
linkedList::linkedList()
{
sentinel.last = &sentinel;
sentinel.next = &sentinel;
sentinel.str = "I am sentinel!!";
}
Secondly, you explicitly call the destructor for linkedList, which results in undefined behaviour when the compiler-arranged destruction is performed as the object leaves the stack scope it's created in - i.e. at the end of main().
I suggest you change node.str to be a std::string, as in any realistic program you'll want to be able to handle variable text, and not just point to (constant) string literals. As is, if you mix string literals and free-store allocated character arrays, you'll have trouble knowing when to call delete[] to release the memory. You could resolve this by always making a new copy of the string data to be stored with new[], but it's safer and easier to use std::string.
Since you allocated it as a local variable, your mylist will be destroyed automatically upon exiting main. Since you've already explicitly invoked its destructor, that leads to undefined behavior (attempting to destroy the same object twice).
As a quick guideline, essentially the only time you explicitly invoke a destructor is in conjunction with placement new. If you don't know what that is (yet), that's fine; just take it as a sign that you shouldn't be invoking destructors.
You forgot to initialize sentinel
In code below you are trying to initialize sentinel (which is not yet constructed) with sentinel(same thing). So you have to pass something to constructor which can be used to initialize your member variable sentinel
*sentinel.last=sentinel;
Also no need to call destructor like this. Destructor will be called once your myList goes out of scope.
myList.~linkedList();
the program may crash, with this:
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel is not initialized sot i has random value on stack.
You're trying to de-reference the pointers last and next of member variable sentinel when they are not yet initialized.
And these de-references *sentinel.last=sentinel *sentinel.next=sentinel are causing the crash because without assigning the values to pointers you're changing the value pointed by the pointers.
You can do like this
sentinel.last=&sentinel;
sentinel.next=&sentinel;
And as pointed out by other explicit destructor calls aren't need here.

In Java, If I change an object reference during a recursive call, does it propogate up?

For example I make the recursive call defined below. The method finds the kth element from the last. If found, it assigns the current node to the object I pass to the recursive call. For some reason the node kth is null. Can you not do things this way? And why?
public void findKthFromLast(Node head, int k){
Node kth;
recrusiveHelper(head, k, kth);
System.out.println(kth.data); //this is null
}
public int recursiveHelper(Node n, int k, Node kthFromLast){
(if n == null){
return 0;
}
val = 1 + recursiveHelper(n.next, k, kthFromlast);
if(k == val){
kthFromLast = n;
}
return val;
}
If the object reference is local to the method, then changes to it wont be visible to caller or anyone else.
E.g:
void caller()
{
obj = new String("asdf");
doStuff(obj)
System.out.println(obj) // still prints "asdf"
}
void doStuff(String obj)
{
// obj is a local reference, changing it wont affect caller's ref
obj = new String("ghj");
}
Firstly, that code shouldn't compile because kth is not initialized and so cannot be used as argument for the recursiveHelper method call.
Secondly, any changes to the references in a called method are not propagated to the caller in Java, i.e.
private void caller()
{
StringBuilder s = new StringBuilder();
s.append("test");
calledMethod1(s);
System.out.println(s.toString());
calledMethod2(s);
System.out.println(s.toString());
}
private void calledMethod1(StringBuilder buffer)
{
buffer = new StringBuilder();
buffer.append("calledMethod1");
return;
}
private void calledMethod2(StringBuilder buffer)
{
buffer.append(", calledMethod2");
return;
}
Output:
test
test, calledMethod2
The reason is, in calledMethod1 you are merely changing what buffer reference points to but not making any changes to what buffer reference was pointing when the method was called. In calledMethod2, you are making changes to the object referred by buffer and hence the changes are visible in the caller.
If you are someone coming from C or C++ background, this is equivalent to assigning to a pointer argument in a called method which doesn't affect what was passed in the caller.
public void findKthFromLast(Node head, int k){
Node kth;
recrusiveHelper(head, k, kth);
System.out.println(kth.data); //this is null
}
You pass null to the method, whatever you do inside that method, outside this will remain being null. You cannot change the value of reference in a way that is visible outside of method doing so.

Categories

Resources