Synchronize access to particular indexes in int array - java

I use the int array.
I use that method to fill indexes in array.
public void makeSelectionOfGivenNumber(int number) throws InterruptedException
{
if (this.table[number]!= 0)
{
int multiple;
multiple = number + number;
while (multiple <= upperRange)
{
this.table[multiple] = 0;
multiple += number;
}
}
}
For example, one thread starts from 2 and eliminates all multiples, a second thread starts from 5 and makes the same activities. In some case the simultaneously the value in index 10 (in both cases are multiples). How to use in this case semaphores or other tools to lock that only one thread has access on particular index, not the whole array. I want that these two threads would work in parallel on the same table.

I think You need to create an additional array of locks (ReadWriteLock, a dimension of the array is how you want) and before each attempt to read/change in the target array to take a lock on reading or on writing the element into the array. To take the lock need to calculate an index from the required index of target array and the capacity of the additional array.
Maybe I'm not quite correctly understood the task
public class SomeTask {
private final ReadWriteLock[] locks = locks(5);
private int[] table;
private int upperRange;
public SomeTask(int[] table, int upperRange) {
this.table = table;
this.upperRange = upperRange;
}
public void makeSelectionOfGivenNumber(int number) {
if (this.table[number] != 0) {
int multiple;
multiple = number + number;
while (multiple <= upperRange) {
ReadWriteLock lock = getLock(multiple);
try {
lock.writeLock().lock();
this.table[multiple] = 0;
} finally {
lock.writeLock().unlock();
}
multiple += number;
}
}
}
private ReadWriteLock getLock(int number) {
return locks[(locks.length - 1) & number];
}
private ReadWriteLock[] locks(int size) {
ReadWriteLock[] result = new ReadWriteLock[size];
for (int i = 0; i < size; i++) {
result[i] = new ReentrantReadWriteLock();
}
return result;
}

Related

Is array in java is threadsafe in case : one thread change value, one thread read value?

I write a simple ringbuffer and in method test1() I use one thread is poll() and
one thread is offer(). I test many time but it is always true. Can you explain for me?
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
#SuppressWarnings("unchecked")
public class RingBuffer<T> {
private T[] buffer;
// private volatile T[] buffer;
private int readIndex;
private int writeIndex;
private final int capacity;
private AtomicInteger size;
public RingBuffer(int k) {
this.buffer = (T[]) new Object[k];
this.capacity = k;
this.readIndex = 0;
this.writeIndex = 0;
this.size = new AtomicInteger(0);
}
public boolean offer(T value) {
if (isFull()) return false;
buffer[writeIndex] = value;
writeIndex++;
if (writeIndex == capacity) writeIndex -= capacity;
size.getAndIncrement();
return true;
}
public T poll() {
if (isEmpty()) return null;
int index = readIndex;
T x = buffer[index];
readIndex++;
if (readIndex == capacity) readIndex -= capacity;
size.getAndDecrement();
return x;
}
public boolean isEmpty() {
return size.get() == 0;
}
public boolean isFull() {
return size.get() == capacity;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
test1();
}
}
As you see in the test1() method I use different Thread but the check is true.
Sorry because stackoverflow warning me this question is mostly code so I will paste test1() method in here.
public static void test1() throws ExecutionException, InterruptedException {
RingBuffer<String> buffer = new RingBuffer<>(1000);
AtomicBoolean writeDone1 = new AtomicBoolean(false);
ExecutorService service = Executors.newFixedThreadPool(2);
ExecutorService service1 = Executors.newFixedThreadPool(2);
Callable<List<String>> cw1 = () -> {
List<String > x = new ArrayList<>();
int count = 0;
for (int i = 0; i < 10000000; i++) {
if (buffer.offer( i+"")) {
count++;
x.add(i+"");
}
}
writeDone1.set(true);
System.out.println("num write " + count);
return x;
};
Callable<List<String>> cr = () -> {
List<String> x = new ArrayList<>();
int count = 0;
while (!writeDone1.get()) {
String data = buffer.poll();
if (data != null) {
x.add(data);
count++;
}
}
while (true) {
String data = buffer.poll();
if (data != null) {
x.add(data);
count++;
} else {
break;
}
}
System.out.println("num read " + count);
return x;
};
Future<List<String >> fw = service.submit(cw1);
Future<List<String>> fr = service1.submit(cr);
List<String> sw = fw.get();
List<String> sr = fr.get();
System.out.println(sw.size());
System.out.println(sr.size());
boolean check = true;
for (int i =0 ; i< sw.size() ; i++){
if (!sw.get(i).equals( sr.get(i))){
check = false;
break;
}
}
System.out.println(check);
service.shutdown();
service1.shutdown();
}
If I use only one consumer and producer. I can't write a test make the race conditions here. Can you help me?
Thankyou
If there are one consumer and one producer, then this RingBuffer is thread-safe.
Happens-before is provided by AtomicInteger size: it is read at the start and is written at the end of both poll() and offer().
For example, let's look at poll().
Notice that:
in poll() we read buffer[index] only if we've read size.get()!=0
size.get()!=0 can only happen after size.getAndIncrement() in offer()
size is AtomicInteger, which means it provides happens-before and makes all modifications in offer() visible in poll()
In other words:
buffer[writeIndex]=value in offer()
-(happens-before)-> size.getAndIncrement() in offer()
-(happens-before)-> size.get()!=0 in poll()
-(happens-before)-> T x = buffer[index] in poll()
There is no happens before edge between a write to an array at some position and a read from the same position. So if you don't have any ordering guarantee in place, your code is suffering from a data race.
If you also allow for concurrent offers and concurrent polls, then you also have race conditions on your hands.
It has been quite some time I played with ringbuffers. But normally you make use of a tail and head sequence (e.g. a long). If you make the ringbuffer a power of 2, you can do a cheap mod on the conversion of the sequences to indices. And the head and tail sequence could be relatively expensive volatiles (I really would start with that) and later on you could play with relaxed memory order modes. The head and tail will give you the appropriate happens before edges so don't need to do anything special to the array. With this approach you can also get rid of the 'size'; you can calculate the size as the difference between tail and thehead; the problem with size is that it will cause contention between a thread read/writing to the ringbuffer. Also you need to properly pad the the head/tail fields to prevent false sharing.

Number is not added at back of existing array

Learning about Arrays. I am not able to figure out why a new number is not added to the back of my existing array. I read in two textfiles in file_1.txt are the numbers '1 2 3' and in file_2.txt is the number '91'. Basically without the method of Void addBack() the program does what I expect, however by adding the method it seems not make a new Array. Even when I go over the elements[i] = elements[i-1] it won't print it as a whole. I am expecting to print for the first part
The numbers are: 1 2 3 and the second part The numbers are: 1 2 3 91.
public class ExampleLecture {
IntRow readIntRow(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.add(input.nextInt());
}
return result;
}
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while(input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
void print(IntRow row) {
for (int i = 0; i < row.numberOfElements; i++) {
System.out.printf("%d ", row.elements[i]);
}
System.out.printf("\n");
}
void start() {
Scanner in = UIAuxiliaryMethods.askUserForInput().getScanner();
Scanner in2 =UIAuxiliaryMethods.askUserForInput().getScanner();
IntRow row = readIntRow(in);
IntRow row2 = setBack(in2);
System.out.printf("the numbers are: ");
print (row);
System.out.printf("the new numbers are: ");
print (row2);
}
public static void main(String[] args) {
new ExampleLecture().start();
}
}
package examplelecture;
class IntRow {
static final int MAX_NUMBER_OF_ELEMENTS = 250;
int[] elements;
int numberOfElements;
IntRow() {
elements = new int[MAX_NUMBER_OF_ELEMENTS];
numberOfElements = 0;
}
void add(int number) {
elements[numberOfElements] = number;
numberOfElements += 1;
}
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
elements[i] = number;
}
}
}
You have 2 successive assignments which write to the same position:
elements[i] = elements[i-1];
elements[i] = number;
The value is alway overwritten with number, so the first statement has no effect.
Also in your addBack method your for cycle:
for (int i = numberOfElements; i>0; i--) {
What happens if numberOfElements is 0?
You call it addBack but it looks like a better name for the method is addFirst. Usually index 0 is considered the front, not the back.
First off, both the readIntRow() and setBack() methods create new IntRow objects row and row2. If you want the result to be appended to the first IntRow object created i.e. to row , you should call:
IntRow row = readIntRow(in);
IntRow row2 = row.setBack(in2);
and setBack() needs to be modified to:
IntRow setBack(Scanner input) {
while(input.hasNext()) {
this.add(input.nextInt());
System.out.println("here");
}
return this;
}
Note that in setBack(), if you are trying to append numbers to the end of the IntRow object, you should call add() instead of addBack() as above. If you are trying to add to the front, you should call addBack() [and it might be better to call it addFront() instead].
Also, in the implementation of addBack(), if you are trying to add to the front of the IntRow object, the element[i] = number operation should take place only once, after the loop. Otherwise all the values in indices <= numberOfElements would be overwritten with number.
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
}
elements[0] = number;
}
Admittedly it is not entirely clear what you are trying to accomplish. But you may have several problems. The first is as follows:
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
IntRow has nothing in it since it is new. So all you are doing is iterating over the new file which has just 91 in it. Remember, result has no items. So it won't even iterate once in addBack.
So just do the following:
Change your addBack method to just add the numbers. Why use a loop to cascade down the elements since you are doing this within the same instance of IntRow? Just add it on to the end using the numberofElements as the next index.
void addBack(int number) {
elements[numberOfElements++] = number;
}
If you want to copy the contents of one IntRow object to another you would need another method in the IntRow class. Something like:
public void copy(IntRow r) {
for (int i = 0; i < r.numerOfElements; i++) {
elements[i] = r.elements[i];
}
numerOfElements = r.numberOfElements;
}
And keeping with good design it might be better to return numberOfElements in a method such as public int size();

Java visibility and synchronization - Thinking in Java example

I read now Thinking in Java, chapter about atomicity and visibility. There is an example I don't understand.
public class SerialNumberGenerator {
private static volatile int serialNumber = 0;
public static int nextSerialNumber() {
return serialNumber++;
}
}
class CircularSet {
private int[] array;
private int len;
private int index = 0;
public CircularSet(int size) {
array = new int[size];
len = size;
for (int i = 0; i < size; i++) {
array[i] = -1;
}
}
synchronized void add(int i) {
array[index] = i;
index = ++index % len;
}
synchronized boolean contains(int val) {
for (int i = 0; i < len; i++) {
if (array[i] == val)
return true;
}
return false;
}
}
public class SerialNumberChecker {
private static final int SIZE = 10;
private static CircularSet serials = new CircularSet(1000);
private static ExecutorService exec = Executors.newCachedThreadPool();
static class SerialChecker implements Runnable {
#Override
public void run() {
while (true) {
int serial = SerialNumberGenerator.nextSerialNumber();
if (serials.contains(serial)) {
System.out.println("Duplicate: " + serial);
System.exit(0);
}
serials.add(serial);
}
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < SIZE; i++) {
exec.execute(new SerialChecker());
}
}
}
example output:
Duplicate: 228
I don't understand how is it possible. Even method nextSerialNumber() is not synchronized and all thread generate different values each thread has own value of serial and each are different. So how is it possible to find duplicate. I cannot imagine of threads execution.
This example shows the post-increment operator is not atomic and not thread-safe.
What happens in this code is:
many (up to 100) threads are started, each executing the same code
in an infinite loop:
an unsynchronized method nextSerialNumber is called, which returns the result of the post-increment operator called on a static variable
a synchronized method contains is called, which checks if the returned value exists in the underlying collection
if yes, the program is terminated
if not, the value is added to the underlying collection
If the post-increment operation was thread-safe then the program would never print "Duplicate" and would never terminate,
since every thread would be getting a different serial number value. This is not the case as two threads
might get exactly the same serial number value.

Java threading issue?

I am wondering why the result is not 400 000. There are two threads why does it gets blocked?
class IntCell {
private int n = 0;
public int getN() {return n;}
public void setN(int n) {this.n = n;}
}
class Count extends Thread {
private static IntCell n = new IntCell();
#Override public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n.getN());
}
}
Why there is so problem with that?
Because the way you increment your variable is not an atomic operation indeed to increment it you:
Get the previous value
Add one to this value
Set a new value
They are 3 operations not done atomically you should either us a synchronized block or use an AtomicInteger instead.
With a synchronized block it would be something like:
synchronized (n) {
temp = n.getN();
n.setN(temp + 1);
}
With an AtomicInteger you will need to rewrite your code as next:
class IntCell {
private final AtomicInteger n = new AtomicInteger();
public int getN() {return n.get();}
public void incrementN(int n) {this.n.addAndGet(n);}
}
for (int i = 0; i < 200000; i++) {
n.incrementN(1);
}
The approach with an AtomicInteger is non blocking so it will be faster
When two threads access one object at the same time, they interfere with each other, and the result is not deterministic. For example, imagine that p reads the value of n and gets, say, 0, then q reads the same value and gets 0 too, then p sets value to 1 and q also sets it to 1 (because it still thinks that it has value 0). Now the value of n is increased by 1, even though both counters "incremented" it once. You need to use synchronized block to make sure the counters won't interfere with each other. See https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html for more.
The problem here is that you allow for race conditions. Consider the block inside the loop:
temp = n.getN();
n.setN(temp + 1);
The code context switch between the time you get the current N and by the time you increment it, making you set an "old" value. One way around this is to ensure the inner part of the loop runs in a synchronized block:
for (int i = 0; i < 200000; i++) {
synchronized (n) { / Here!
temp = n.getN();
n.setN(temp + 1);
}
}

Using a data structure to solve this in O(n)

we have sequence of 4 characters (A,B,C and D)that map to numbers form 1 to n.
we define components to be:
Component(k) :
A {cell[k]}
if Color(left_k) = Color(k)
then
A <-- A U Component(left_k)
if Color(right_k) = Color(k)
then
A <-- A U Component(left_k)
return A
there is 3 types of operations(the numbers in list indicate the input):
by giving index it should remove the component in that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return AADA
by giving index it should rotate the string based on the component on that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return DABBBAA
it should print the string.
inputs are like:
1 2 --> first operation with index=2
2 3 --> second operation with index=3
3 --> third operation
It's an assignment, happy to get help.
this is what i've tried so far:
public static void main(String[] args)
{
int numberOfOps;
String[] print = new String[30];
List list = new List();
Scanner input = new Scanner(System.in);
int count = input.nextInt();
String colors = new String();
colors = input.next();
for(int i = 0; i < count; i++)
{
list.add(colors.charAt(i));
}
numberOfOps = input.nextInt();
list.printElement();
for (int i = 0; i < numberOfOps; i++)
{
int op = input.nextInt();
if(op == 1)
{
int index = input.nextInt();
char c = list.item[index];
int temp = index;
int prevIndex = index;
int nexIndex = index;
if(index != 0)
{
while (list.item[--index] == c)
{
prevIndex--;
}
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex-1, nexIndex+1);
}
else
{
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex, nexIndex+1);
}
}
if(op == 2)
{
int index = input.nextInt();
}
if(op == 3)
{
print[i] = list.printElement();
}
}
}
here is my List class:
public class List {
// reference to linked list of items
public static final int MAX_LIST = 20;
public static final int NULL = -1;
public char item[] = new char[MAX_LIST]; // data
public int avail;
public int next[] = new int[MAX_LIST]; // pointer to next item
private int numItems; // number of items in list
public List()
{
int index;
for (index = 0; index < MAX_LIST-1; index++)
next[index] = index + 1;
next[MAX_LIST-1] = NULL;
numItems = 0;
avail = 0;
} // end default constructor
public void add(char e)
{
item[avail] = e;
avail = next[avail];
numItems++;
}
public String printElement()
{
String temp = null;
int index = 0;
while(index<avail)
{
temp += item[index];
System.out.println(item[index]);
index = next[index];
}
return temp;
}
public int size()
{
return numItems;
}
public void setNext(int i, int value)
{
next[i] = value;
}
}
if you test it you'll get, it has lots of problems, such as, I have no idea to do the rotate operation, and it has problem with connecting two components when the middle component has been removed.
This is a difficult question to answer, because the requirements are not properly stated.
For example the first bunch of pseudo-code does not make it clear whether A is a set, a multi-set or a list. The notation (use of curly brackets, and U (union?)) seems to say set ... but the output seems to be a list. Or maybe it is supposed to be a schema for a data structure??
And even the inputs are not clearly described.
But putting that on one side, there is still room for some (hopefully) helpful advice.
Make sure that >>you<< understand the requirements. (I imagine that the real requirements for the assignment are better stated than this, and the details have been "lost in translation".)
I would actually use an array list (or a StringBuilder) rather than a linked list for this. (But a properly implemented linked list ... implementing the List API ... would work.)
But whatever data structure you chose, there is no point in implementing it from scratch ... unless you are specifically required to do that. There are perfectly good list classes in the Java standard libraries. You should reuse them ... rather than attempting to reinvent the wheel (and doing a bad job).
If you are required to implement your own data structure type, then your current attempt is a mess. It looks like a hybrid between an array list and a linked list ... and doesn't succeed in being either. (For example, a decent array list implementation does not need a MAX_LIST, and doesn't have next pointers / indexes. And a linked list does not have any arrays inside it.)

Categories

Resources